前言
为了让全景更加生动,营造视觉奇观和增强视觉效果,我们往往会在全景更里面增加一些特效,例如飘落特效和太阳光特效等,这篇文章就来实现如何在全景中为场景添加飘落特效
预览效果
1.snow.js插件的使用
1.1snow.js插件介绍
飘落特效主要使用krpano提供的插件snow.js ,这是官方实例,这是一个天气效果插件,可以为全景添加雪雨(像素)或者自定义的图像
插件中的所有属性都可以动态设置或更改,snow.js插件提供了以下属性:
mode
:可以设置的值有snow,rain,image,雨雪像素的颜色可以通过color
属性定义,掉落的线条则通过rainwidth
和rainalpha
属性用来模拟下雨,image代表使用自定义图像,必须设置imageurl
属性imageurl
:图像的地址imagescale
:图像的缩放比例,默认为1.0flakes
:特效的数量,默认为4000color
:特效的颜色,默认为0xFFFFFFfloor
:地面高度,定义了一个虚拟地面,特效到达则停止掉落,设置的范围为 0.0 到 1.0,设置 0.0 地面高度为全景/屏幕的中间,默认设置为 0.3speed
:飘落的速度,默认1.0spreading
:范围/深度,默认为4.0shake
:特效抖动范围,默认为4.0speedvariance
:特效下落速度的随机变化,默认为2.0wind
:改变特效飘落方向的风力,默认为0.0winddir
:风向(以度为单位),0-360,默认为0rainwidth
:雨滴线的线宽,默认为0.5rainalpha
:雨滴线的透明度,默认为0.5invert
:图像坠落方向,向上/向下,默认为false
1.2使用插件
使用插件首先要导入插件,可以使用include元素将其他xml文件的内容嵌入到主xml中,krpano安装包中就包含了snow.xml 示例文件,在krpanos\viewer\examples\snow文件夹下

然后在想要的场景中导入,并在onstart的时候加载特效(执行action动作)
js
// onready回调
const onReadyCallBack = (kp: any) => {
const content = `
<control bouncinglimits="calc:image.cube ? true : false" />
<view hlookat="0.0" vlookat="0.0" fovtype="MFOV" fov="120" maxpixelzoom="2.0" fovmin="70" fovmax="140" limitview="auto" />
<preview url="krpano/pano/login/preview.jpg" />
<image>
<cube url="krpano/pano/login/%s/l%l/%v/l%l_%s_%v_%h.jpg" multires="512,1024,2048" />
</image>
<include url="krpano/plugins/snow/snow.xml" />
`
kp.set('scene[scene_login].title', 'anima_scene')
kp.set('scene[scene_login].thumburl', 'krpano/pano/login/thumb.jpg')
kp.set('scene[scene_login].onstart', 'snowflakes();')
kp.set('scene[scene_login].content', content)
}

2.自定义特效
但是这样只能在加载场景的时候选择是否使用include来引入插件,无法动态的include引入,所以krpano为我们提供了一个addplugin方法
,可以动态的引入插件,不止插件也可以动态创建layer、hotspot元素等
addplugin方法引入snow.js插件之后就可以设置对应的属性了,特效的模式我都使用自定义的图像
js
// 加载特效
kp.addplugin(uid)
kp.set(`plugin[${uid}].zorder`, 1)
kp.set(`plugin[${uid}].url`, '%SWFPATH%/plugins/snow/snow.js')
kp.set(`plugin[${uid}].alturl`, '%SWFPATH%/plugins/snow/snow.js')
kp.set(`plugin[${uid}].mode`, sys_effect[index].mode)
kp.set(`plugin[${uid}].blendmode`, 'add')
kp.set(`plugin[${uid}].imageurl`, OSS_PATH + '/' + sys_effect[index].path)
kp.set(`plugin[${uid}].invert`, !!effectObj.invert)
kp.set(`plugin[${uid}].imagescale`, effectObj.imagescale)
kp.set(`plugin[${uid}].flakes`, effectObj.flakes)
kp.set(`plugin[${uid}].speed`, effectObj.speed)
kp.set(`plugin[${uid}].speedvariance`, effectObj.speedvariance)
kp.set(`plugin[${uid}].floor`, effectObj.floor)
kp.set(`plugin[${uid}].shake`, effectObj.shake)
kp.set(`plugin[${uid}].wind`, effectObj.wind)
kp.set(`plugin[${uid}].winddir`, effectObj.winddir)
然后就可以根据自己的需要去编辑设置特效的属性了,通过antd的Slider
组件来绑定对象的属性,当Slider的值发生改变时,触发onChange事件,拿到改变后的值通过set
方法去更新
js
// 运动方向变化
const onInvertChange = (value: number) => {
kp.set(`plugin[${id}].invert`, !!value)
}
// 特效缩放变化
const onScaleChange = (value: number) => {
kp.set(`plugin[${id}].imagescale`, value)
}
// 特效数量变化
const onFlakesChange = (value: number) => {
kp.set(`plugin[${id}].flakes`, value)
}
// 运动速度变化
const onSpeedChange = (value: number) => {
kp.set(`plugin[${id}].speed`, value)
}
// 运动速度变化变化
const onSpeedvarianceChange = (value: number) => {
kp.set(`plugin[${id}].speedvariance`, value)
}
// 虚拟地板高度变化
const onFloorChange = (value: number) => {
kp.set(`plugin[${id}].floor`, value)
}
// 特效抖动变化
const onShakeChange = (value: number) => {
kp.set(`plugin[${id}].shake`, value)
}
// 风力变化
const onWindChange = (value: number) => {
kp.set(`plugin[${id}].wind`, value)
}
// 风向变化
const onWinddirChange = (value: number) => {
kp.set(`plugin[${id}].winddir`, value)
}
当切换场景的时候,需要移除当前场景的所有特效,以及加载下一个场景的特效,否则下一场景还会存在前一个场景的特效 addplugin方法对应的就是removeplugin方法,用来移除指定的插件,所以在切换场景的时候移除对应特效插件
js
// 切换场景
const onSceneChange = (nextScene: ISceneType) => {
// 判断前一场景特效列表长度
if (scene?.effect.length) {
scene.effect.forEach((item) => {
kp.removeplugin(item.id)
})
}
}
并且在新场景中创建特效
js
useEffect(() => {
scene.effect.forEach((item) => {
kp.addplugin(item.id)
kp.set(`plugin[${item.id}].zorder`, 1)
kp.set(`plugin[${item.id}].url`, '%SWFPATH%/plugins/snow/snow.js')
kp.set(`plugin[${item.id}].alturl`, '%SWFPATH%/plugins/snow/snow.js')
kp.set(`plugin[${item.id}].mode`, item.mode)
kp.set(`plugin[${item.id}].blendmode`, 'add')
kp.set(`plugin[${item.id}].imageurl`, OSS_PATH + '/' + item.imageurl)
kp.set(`plugin[${item.id}].invert`, !!item.invert)
kp.set(`plugin[${item.id}].imagescale`, item.imagescale)
kp.set(`plugin[${item.id}].flakes`, item.flakes)
kp.set(`plugin[${item.id}].speed`, item.speed)
kp.set(`plugin[${item.id}].speedvariance`, item.speedvariance)
kp.set(`plugin[${item.id}].floor`, item.floor)
kp.set(`plugin[${item.id}].shake`, item.shake)
kp.set(`plugin[${item.id}].wind`, item.wind)
kp.set(`plugin[${item.id}].winddir`, item.winddir)
})
}, [sceneid])

结尾
以上就是我对场景添加特效的实现,如果还有更好的方式也欢迎大家一起分享交流,学习学习😊🤞💋😘