【强化学习】DDPG : 强化学习之倒立摆

DPG是确定策略梯度 (Deterministic Policy Gradient, DPG)是最常用的连续控制方法。DPG是一种 Actor-Critic 方法,它有一个策略网络(演员),一个价值网络(评委)。策略网络控制智能体做运动,它基于状态 s 做出动作 a。价值网络不控制智能体,只是基于状态 s 给动作 a 打分,从而指导策略网络做出改进。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【强化学习】ddpg : 强化学习之倒立摆 - 创想鸟

DDPG

DPG是确定策略梯度 (Deterministic Policy Gradient, DPG)是最常用的连续控制方法。DPG是一种 Actor-Critic 方法,它有一个策略网络(演员),一个价值网络(评委)。策略网络控制智能体做运动,它基于状态 s 做出动作 a。价值网络不控制智能体,只是基于状态 s 给动作 a 打分,从而指导策略网络做出改进。【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

倒立摆问题:

倒立摆问题的经典的连续控制问题,钟摆以随机位置开始,目标是将其向上摆动,使其保持直立。其状态空间为3,动作空间为1(因为是连续的,有范围)。具体可以参考下图:

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

项目目标

使用深度神经网络DPG训练模型,也就是DDPG方法,使其在倒立摆环境中能够获得较好的奖励。

1.加载环境

In [1]

import gymimport paddlefrom itertools import countimport numpy as npfrom collections import dequeimport randomimport timefrom visualdl import LogWriter

   

2.定义网络

2.1 定义 【评论家】 网络结构

DDPG这种方法与Q学习紧密相关,可以看做是 【连续】动作空间的深度Q学习【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

In [2]

class Critic(paddle.nn.Layer):    def __init__(self):        super(Critic,self).__init__()               # 状态空间为3        self.fc1=paddle.nn.Linear(3,256)               # 连接了动作空间,所以+1        self.fc2=paddle.nn.Linear(256+1,128)        #         self.fc3=paddle.nn.Linear(128,1)        self.relu=paddle.nn.ReLU()        def forward(self,x,a):        x=self.relu(self.fc1(x))        x=paddle.concat((x,a),axis=1)        x=self.relu(self.fc2(x))        x=self.fc3(x)        return x

   

2.2 定义【演员】网络结构

为了使DDPG策略更好的进行探索,在训练时对其行为增加了干扰。原始DDPG论文建议使用时间相关的OU噪声,但最近的结果表明,【不相关的均值零高斯噪声】效果更好。后者更简单,首选。【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

In [3]

class Actor(paddle.nn.Layer):    def __init__(self,is_tranin=True):        super(Actor,self).__init__()                self.fc1=paddle.nn.Linear(3,256)        self.fc2=paddle.nn.Linear(256,128)        self.fc3=paddle.nn.Linear(128,1)        self.relu=paddle.nn.ReLU() # max(0,x)        self.tanh=paddle.nn.Tanh() # 双切正切曲线 (e^(x)-e^(-x))/(e^(x)+e^(-x))        self.noisy=paddle.distribution.Normal(0,0.2)        self.is_tranin=is_tranin        def forward(self,x):        x=self.relu(self.fc1(x))        x=self.relu(self.fc2(x))        x=self.tanh(self.fc3(x))        return x        def select_action(self,epsilon,state):        state=paddle.to_tensor(state,dtype='float32').unsqueeze(0)        # 创建一个上下文来禁用动态图梯度计算。在此模式下,每次计算的结果都将具有stop_gradient=True。        with paddle.no_grad():            # squeeze():会删除输入Tensor的Shape中尺寸为1的维度            # noisy抽样结果是1维的tensor            action=self.forward(state).squeeze()+self.is_tranin*epsilon*self.noisy.sample([1]).squeeze(0)                # paddle.clip:将输入的所有元素进行剪裁,使得输出元素限制在[min, max]内        # 动作空间是[-2,2]        return 2*paddle.clip(action,-1,1).numpy()

   

2.3 定义 经验回放buffer(重播缓冲区)

这是智能体以前的经验,为了使算法具有稳定的行为,重播缓冲区应该足够大以包含广泛的经验。

如果仅使用最新的经验,则可能会过分拟合;如果使用过多的旧经验,则可能减慢模型的学习速度。

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

In [4]

class Memory(object):       def __init__(self,memory_size):        self.memory_size=memory_size        self.buffer=deque(maxlen=self.memory_size)        # 增加经验,因为经验数组是存放在deque中的,deque是双端队列,    # 我们的deque指定了大小,当deque满了之后再add元素,则会自动把队首的元素出队    def add(self,experience):        self.buffer.append(experience)        def size(self):        return len(self.buffer)    # continuous=True则表示连续取batch_size个经验    def sample(self , batch_szie , continuous = True):        # 选取的经验数目是否超过缓冲区内经验的数目        if batch_szie>len(self.buffer):            batch_szie=len(self.buffer)                # 是否连续取经验        if continuous:            # random.randint(a,b) 返回[a,b]之间的任意整数            rand=random.randint(0,len(self.buffer)-batch_szie)            return [self.buffer[i] for i in range(rand,rand+batch_szie)]        else:            # numpy.random.choice(a, size=None, replace=True, p=None)            # a 如果是数组则在数组中采样;a如果是整数,则从[0,a-1]这个序列中随机采样            # size 如果是整数则表示采样的数量            # replace为True可以重复采样;为false不会重复            # p 是一个数组,表示a中每个元素采样的概率;为None则表示等概率采样            indexes=np.random.choice(np.arange(len(self.buffer)),size=batch_szie,replace=False)            return [self.buffer[i] for i in indexes]        def clear(self):        self.buffer.clear()

   

3. 训练DPG模型

3.1 原始的DPG

3.1.1 定义环境、实例化模型

In [5]

env=gym.make('Pendulum-v0')actor=Actor()critic=Critic()

       

W1225 22:38:55.283380   289 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1W1225 22:38:55.287163   289 device_context.cc:465] device: 0, cuDNN Version: 7.6.

       

3.1.2 定义优化器

In [6]

critic_optim=paddle.optimizer.Adam(parameters=critic.parameters(),learning_rate=3e-5)actor_optim=paddle.optimizer.Adam(parameters=actor.parameters(),learning_rate=1e-5)

   

3.1.3 定义超参数

In [7]

explore=50000epsilon=1 # 控制动作的抽样gamma=0.99tau=0.001memory_replay=Memory(50000)begin_train=Falsebatch_szie=32learn_steps=0epochs=100writer=LogWriter('./logs')

   

3.1.4 训练循环

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

In [8]

s_time=time.time()for epoch in range(0,epochs):    start_time=time.time()    state=env.reset()    episode_reward=0 # 记录一个epoch的奖励综合    # 一个epoch进行2000的时间步    for time_step in range(2000):        # 步骤1,策略网络根据初始状态做预测        action=actor.select_action(epsilon,state)        next_state,reward,done,_=env.step([action])        episode_reward+=reward        # 这一步在做什么? reward [-1,1]        reward=(reward+8.2)/8.2        memory_replay.add((state,next_state,action,reward))        # 当经验回放数组中的存放一定量的经验才开始利用        if memory_replay.size()>1280:            learn_steps+=1            if not begin_train:                print('train begin!')                begin_train=True                        # false : 不连续抽样            experiences=memory_replay.sample(batch_szie,False)            batch_state,batch_next_state,batch_action,batch_reward=zip(*experiences)            batch_state=paddle.to_tensor(batch_state,dtype='float32')            batch_next_state=paddle.to_tensor(batch_next_state,dtype='float32')            batch_action=paddle.to_tensor(batch_action,dtype='float32').unsqueeze(1)            batch_reward=paddle.to_tensor(batch_reward,dtype='float32').unsqueeze(1)                        with paddle.no_grad():                                # 策略网络做预测                at,at1=actor(batch_state),actor(batch_next_state)                # 价值网络做预测                qt,qt1=critic(batch_state,batch_action),critic(batch_next_state,at1)                # 计算TD目标                Q_traget=batch_reward+gamma*qt1                        # TD误差函数            # 该OP用于计算预测值和目标值的均方差误差。(预测值,目标值)            # reduction='mean',默认值,计算均值            critic_loss=paddle.nn.functional.mse_loss(qt,Q_traget)            # 更新价值网络            critic_optim.clear_grad()            critic_loss.backward()            critic_optim.step()            writer.add_scalar('critic loss',critic_loss.numpy(),learn_steps)            # 更新策略网络            critic.eval()            actor_loss=-critic(batch_state,at)            actor_loss=actor_loss.mean()            actor_optim.clear_grad()            actor_loss.backward()            actor_optim.step()            critic.train()            writer.add_scalar('actor loss',actor_loss.numpy(),learn_steps)        # epsilon 逐渐减小        if epsilon>0:            epsilon-=1/explore        state=next_state         writer.add_scalar('episode reward',episode_reward/2000,epoch)        if epoch%10==0:        print("Epoch:{}, episode reward is {:.3f}, use time is {:.3f}s ".format(epoch,episode_reward/2000,time.time()-start_time))    print("************ all time is {:.3f} h:".format((time.time()-s_time)/3600))

       

train begin!

       

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/tensor/creation.py:130: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations  if data.dtype == np.object:

       

Epoch:0, episode reward is -6.058, use time is 4.891s Epoch:10, episode reward is -6.146, use time is 11.346s Epoch:20, episode reward is -6.144, use time is 11.830s Epoch:30, episode reward is -7.270, use time is 11.998s Epoch:40, episode reward is -6.148, use time is 11.932s Epoch:50, episode reward is -7.335, use time is 12.149s Epoch:60, episode reward is -6.411, use time is 12.301s Epoch:70, episode reward is -6.135, use time is 12.365s Epoch:80, episode reward is -6.768, use time is 12.136s Epoch:90, episode reward is -6.219, use time is 12.191s ************ all time is 0.329 h:

       

3.1.5 结果展示及分析

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

奖励在-6左右徘徊,说明网络效果不好(奖励越靠近0越好)。下面加入目标网络进行实验。

立即进入“豆包AI人工智官网入口”;

立即学习“豆包AI人工智能在线问答入口”;

3.2 加入目标网络的DPG

加入目标网络的作用是缓解高估问题,DPG中的高估来自两个方面:

自举:TD目标用价值网络算出来的,而它又被用于更新价值网络 q 本身,这属于自举。自举会造成偏差的传播。最大化:在训练策略网络的时候,我们希望策略网络计算出的动作得到价值网络尽量高的评价。在求解的过程中导致高估的出现。

自举与最大化的分析可参考王书的10.3.3节,分析的挺不错,但是推理比较复杂,这里就不再描述了,主要把结论记住就好。(陶渊明说读书要不求甚解,嘿嘿)

3.2.1 定义网络、优化器、超参数

这里我们重新定义了所有参数,即使前面定义过,因为有的参数是不断更新的(值变了),所有我们在这里统一重新定义一下。

In [9]

actor=Actor()critic=Critic()critic_optim=paddle.optimizer.Adam(parameters=critic.parameters(),learning_rate=3e-5)actor_optim=paddle.optimizer.Adam(parameters=actor.parameters(),learning_rate=1e-5)# 目标网络,缓解自举造成的高估问题actor_target=Actor()critic_target=Critic()explore=50000epsilon=1 # 控制动作的抽样gamma=0.99tau=0.001memory_replay=Memory(50000)begin_train=Falsebatch_szie=32learn_steps=0epochs=100twriter=LogWriter('./newlogs')

   

3.2.2 定义目标网络的更新函数

更新目标网络参数,公式如下:

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

In [10]

def soft_update(target,source,tau):    # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。    for target_param,param in zip(target.parameters(),source.parameters()):        target_param.set_value(target_param*(1.0-tau)+param*tau)

   

3.2.3 训练过程

策略网络根据当前状态进行动作选择执行该动作,得到新状态,奖励(旧状态,动作,奖励,新状态) 四元组进入经验回放数组当经验数组内四元组数量大于阈值则选取一部分经验更新网络:从经验数组中随机抽取四元组(s_t,a_t,r_t,s_t+1)目标策略网络做预测,输入是 s_t+1 预测出下一个动作a_t+1目标价值网络做预测,输入是s_t+1和a_t+1,输出是q_tt计算TD目标,y= r_t+gamma*q_tt价值网络做预测,输入是s_t,a_t,输出是q_t计算TD误差,error=q_t-y更新价值网络更新策略网络更新目标网络

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

In [11]

s_time=time.time()k=0for epoch in range(0,epochs):    start_time=time.time()    state=env.reset()    episode_reward=0 # 记录一个epoch的奖励综合    # 一个epoch进行2000的时间步    for time_step in range(2000):        # 步骤1,策略网络根据初始状态做预测        action=actor.select_action(epsilon,state)        next_state,reward,done,_=env.step([action])        episode_reward+=reward        # reward缩放到 [-1,1]        reward=(reward+8.2)/8.2        memory_replay.add((state,next_state,action,reward))        # 当经验回放数组中的存放一定量的经验才开始利用        if memory_replay.size()>1280:            learn_steps+=1            if not begin_train:                print('train begin!')                begin_train=True                        # false : 不连续抽样            # 从经验数组中随机抽取四元组(s_t,a_t,r_t,s_t+1)            experiences=memory_replay.sample(batch_szie,False)            batch_state,batch_next_state,batch_action,batch_reward=zip(*experiences)            batch_state=paddle.to_tensor(batch_state,dtype='float32')            batch_next_state=paddle.to_tensor(batch_next_state,dtype='float32')            batch_action=paddle.to_tensor(batch_action,dtype='float32').unsqueeze(1)            batch_reward=paddle.to_tensor(batch_reward,dtype='float32').unsqueeze(1)            # 目标策略网络做预测,输入是 s_t+1 预测出下一个动作a_t+1            # 目标价值网络做预测,输入是s_t+1和a_t+1,输出是q_tt            # 计算TD目标,y= r_t+gamma*q_tt            with paddle.no_grad():                # Q_next traget是TD目标                Q_next=critic_target(batch_next_state,actor_target(batch_next_state))                Q_traget=batch_reward+gamma*Q_next                        # 价值网络做预测,输入是s_t,a_t,输出是q_t            # 计算TD误差,error=q_t-y            # 误差函数            # 该OP用于计算预测值和目标值的均方差误差。(预测值,目标值)            # reduction='mean',默认值,计算均值            critic_loss=paddle.nn.functional.mse_loss(critic(batch_state,batch_action),Q_traget)                        # 更新价值网络            critic_optim.clear_grad()            critic_loss.backward()            critic_optim.step()            twriter.add_scalar('critic loss',critic_loss.numpy(),learn_steps)            if k==5:                #更新策略网络                # 使用Critic网络给定值的平均值来评价Actor网络采取的行动。最大化该值。                # 更新Actor()网络,对于一个给定状态,它产生的动作尽量让Critic网络给出高的评分                critic.eval()                actor_loss=-critic(batch_state,actor(batch_state))                actor_loss=actor_loss.mean()                actor_optim.clear_grad()                actor_loss.backward()                actor_optim.step()                critic.train()                twriter.add_scalar('actor loss',actor_loss.numpy(),learn_steps)                # 更新目标网络                soft_update(actor_target,actor,tau)                soft_update(critic_target,critic,tau)                k=0            else:                k+=1                # epsilon 逐渐减小        if epsilon>0:            epsilon-=1/explore        state=next_state         twriter.add_scalar('episode reward',episode_reward/2000,epoch)        if epoch%10==0:        print("Epoch:{}, episode reward is {:.3f}, use time is {:.3f}s ".format(epoch,episode_reward/2000,time.time()-start_time))    print("************ all time is {:.3f} h:".format((time.time()-s_time)/3600))

       

train begin!Epoch:0, episode reward is -8.726, use time is 4.682s Epoch:10, episode reward is -7.607, use time is 10.381s Epoch:20, episode reward is -7.419, use time is 11.115s Epoch:30, episode reward is -6.317, use time is 11.464s Epoch:40, episode reward is -8.340, use time is 11.308s Epoch:50, episode reward is -8.306, use time is 11.535s Epoch:60, episode reward is -8.276, use time is 11.356s Epoch:70, episode reward is -1.401, use time is 11.539s Epoch:80, episode reward is -8.145, use time is 11.346s Epoch:90, episode reward is -0.076, use time is 11.321s ************ all time is 0.308 h:

       

3.2.4 加入目标网络后的结果展示

【强化学习】DDPG : 强化学习之倒立摆 - 创想鸟        

奖励在训练的后期可以达到较好的奖励值,但是波动较大。但是与没有加入目标网络的模型相比较结果有所进步。后续有时间继续优化。

以上就是【强化学习】DDPG : 强化学习之倒立摆的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/52594.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月9日 05:14:08
下一篇 2025年11月9日 05:17:47

相关推荐

  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • PC端H5项目如何实现适配:流式布局、响应式设计和两套样式?

    PC端的适配方案及PC与H5兼顾的实现方案探讨 在开发H5项目时,常用的屏幕适配方案是postcss-pxtorem或postcss-px-to-viewport,通常基于iPhone 6标准作为设计稿。但对于PC端网项目,处理不同屏幕大小需要其他方案。 PC端屏幕适配方案 PC端屏幕适配一般采用流…

    2025年12月24日
    300
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000
  • 如何用前端实现 Windows 10 设置界面的鼠标移动探照灯效果?

    如何在前端实现 Windows 10 设置界面中的鼠标移动探照灯效果 想要在前端开发中实现 Windows 10 设置界面中类似的鼠标移动探照灯效果,可以通过以下途径: CSS 解决方案 DEMO 1: Windows 10 网格悬停效果:https://codepen.io/tr4553r7/pe…

    2025年12月24日
    000
  • 使用CSS mask属性指定图片URL时,为什么浏览器无法加载图片?

    css mask属性未能加载图片的解决方法 使用css mask属性指定图片url时,如示例中所示: mask: url(“https://api.iconify.design/mdi:apple-icloud.svg”) center / contain no-repeat; 但是,在网络面板中却…

    2025年12月24日
    000
  • 如何用CSS Paint API为网页元素添加时尚的斑马线边框?

    为元素添加时尚的斑马线边框 在网页设计中,有时我们需要添加时尚的边框来提升元素的视觉效果。其中,斑马线边框是一种既醒目又别致的设计元素。 实现斜向斑马线边框 要实现斜向斑马线间隔圆环,我们可以使用css paint api。该api提供了强大的功能,可以让我们在元素上绘制复杂的图形。 立即学习“前端…

    2025年12月24日
    000
  • 图片如何不撑高父容器?

    如何让图片不撑高父容器? 当父容器包含不同高度的子元素时,父容器的高度通常会被最高元素撑开。如果你希望父容器的高度由文本内容撑开,避免图片对其产生影响,可以通过以下 css 解决方法: 绝对定位元素: .child-image { position: absolute; top: 0; left: …

    2025年12月24日
    000
  • 使用 Mask 导入本地图片时,如何解决跨域问题?

    跨域疑难:如何解决 mask 引入本地图片产生的跨域问题? 在使用 mask 导入本地图片时,你可能会遇到令人沮丧的跨域错误。为什么会出现跨域问题呢?让我们深入了解一下: mask 框架假设你以 http(s) 协议加载你的 html 文件,而当使用 file:// 协议打开本地文件时,就会产生跨域…

    2025年12月24日
    200
  • CSS 帮助

    我正在尝试将文本附加到棕色框的左侧。我不能。我不知道代码有什么问题。请帮助我。 css .hero { position: relative; bottom: 80px; display: flex; justify-content: left; align-items: start; color:…

    2025年12月24日 好文分享
    200

发表回复

登录后才能评论
关注微信