先看效果:
代码如下:
<template><div style="height: 800px"></div><divclass="rainbow-position"ref="host"><divv-for="config in colorStyles"class="one-shadow":style="config"></div></div>
</template><script>
const rainbowColorsBlue = [{heightScale: 0.5,color: '#5cf7ff',},{heightScale: 0.3,color: '#5c9cff',leftOffset: -0.1,},{heightScale: 1,color: '#5275ff',leftOffset: -0.1,blurScale: 1.5,topOffset: -0.5,},{heightScale: 0.3,color: '#a581ff',},
];
// 这个其实没用到
const rainbowColorsGreen = [{heightScale: 0.5,color: '#d5c240',},{heightScale: 0.3,color: '#c2d540',leftOffset: -0.1,},{heightScale: 1,color: '#5ed540',leftOffset: -0.1,blurScale: 1.5,topOffset: -0.5,},{heightScale: 0.3,color: '#5cf7ff',},
];export default {name: 'app',data() {return {originColors: [],nowColors: [],posConfigs: [], // [{top, left, height, blurW},{top, left, height, blurW}]colorStyles: [], // 其实就是为了动态获取这些值 [{left: , top:, height:, box-shadow:, -moz-box-shadow: , -webkit-box-shadow: }]loopTimer: null,colorTimer: null,themeColor: 'blue',// themeColor: 'green',};},created() {this.nowColors =this.themeColor === 'blue'? [...rainbowColorsBlue]: [...rainbowColorsGreen];this.originColors = [...this.nowColors];this.nowColors.push(this.nowColors.shift()); // shift()删除第一个},mounted() {clearTimeout(this.loopTimer);this.loopPosFn();clearTimeout(this.colorTimer);this.loopColorFn();},beforeDestroy() {clearTimeout(this.loopTimer);clearTimeout(this.colorTimer);},methods: {loopPosFn() {this.getPosConfigs();this.calcStyles();let timeout = (1 + (Math.random() - 0.5) * 0.4) * 1000; // 0.8到1.2秒之间this.loopTimer = setTimeout(() => { // 死循环调用this.loopPosFn();}, timeout);},loopColorFn() {this.nowColors.unshift(this.nowColors.pop());this.calcStyles();let timeout = (1 + (Math.random() - 0.5) * 0.3) * 1000;this.colorTimer = setTimeout(() => {this.loopColorFn();}, timeout);console.log("this.colorStyles", this.colorStyles);},getPosConfigs() {let cfgs = [];this.originColors.forEach((color, i) => {cfgs.push(this.getPosConfig(color, i, this.originColors));});this.posConfigs = cfgs;},getPosConfig(colorCfg, index, array) {if (!this.$refs.host) {return;}let { clientWidth, clientHeight } = this.$refs.host;// console.log("clientWidth, clientHeight", clientWidth, clientHeight) // width:100%,这里的100%需要换成像素即可, clientHeight为0因为设置的height=0let spanW = 1 / array.length; // 1/4=0.25// ~ 1 左右移动范围,确定一个leftlet baseLeft = (index + 1) / (array.length + 1); // (0.2, 0.8)let leftOffset = (Math.random() - 0.5) * 0.6 * spanW; // (-0.075, 0.075)if (colorCfg.leftOffset) {leftOffset += colorCfg.leftOffset;}let left = (baseLeft + leftOffset) * clientWidth;// ~ 2 确定扩散宽度 水平let blurScale = spanW * ((Math.random() - 0.5) * 0.2 + 0.55); // 0.25*(0.45, 0.65)if (colorCfg.blurScale) {blurScale *= colorCfg.blurScale;}let blurW = blurScale * clientWidth; //// console.log("blurW", blurW)// ~ 3 高度范围,确定heightlet heightScale = 3 + (Math.random() - 0.5) * 0.6;if (colorCfg.heightScale) {heightScale *= colorCfg.heightScale;}let height = heightScale * clientHeight; // 0 因为clientHeight=0// console.log("height", height)// ~ 4 上下移动范围,确定toplet topOffset = (Math.random() - 0.5) * 0.6;if (colorCfg.topOffset) {topOffset += colorCfg.topOffset;}let top = topOffset * clientHeight;// console.log("top", top); // 0return {left,top,height,blurW,};},calcStyles() {let styles = [];this.posConfigs.forEach((pos, i) => {try {let color = this.nowColors[i].color;let { left, top, height, blurW } = pos;let shadow = `0 0 ${blurW}px ${blurW / 2}px ${color}`;styles.push({left: `${left}px`,top: `${top}px`,height: `${height}px`,'box-shadow': shadow,'-moz-box-shadow': shadow,'-webkit-box-shadow': shadow,});} catch (err) {}});this.colorStyles = styles;},},
};
</script><style lang="less" scoped>
.rainbow-position {position: relative;width: 1000px;.one-shadow {position: absolute;transition: all 1.2s linear;}
}
</style>
本质上还是操作box-shadow的值以及绝对定位中left的值
[{"left": "192.8242165893445px","top": "0px","height": "0px","box-shadow": "0 0 135.25323349796668px 67.62661674898334px #5c9cff","-moz-box-shadow": "0 0 135.25323349796668px 67.62661674898334px #5c9cff","-webkit-box-shadow": "0 0 135.25323349796668px 67.62661674898334px #5c9cff"},{"left": "296.2928408628739px","top": "0px","height": "0px","box-shadow": "0 0 149.301217974191px 74.6506089870955px #5275ff","-moz-box-shadow": "0 0 149.301217974191px 74.6506089870955px #5275ff","-webkit-box-shadow": "0 0 149.301217974191px 74.6506089870955px #5275ff"},{"left": "476.47387807345px","top": "0px","height": "0px","box-shadow": "0 0 188.3680661548236px 94.1840330774118px #a581ff","-moz-box-shadow": "0 0 188.3680661548236px 94.1840330774118px #a581ff","-webkit-box-shadow": "0 0 188.3680661548236px 94.1840330774118px #a581ff"},{"left": "812.9763044334327px","top": "0px","height": "0px","box-shadow": "0 0 116.1677125622857px 58.08385628114285px #5cf7ff","-moz-box-shadow": "0 0 116.1677125622857px 58.08385628114285px #5cf7ff","-webkit-box-shadow": "0 0 116.1677125622857px 58.08385628114285px #5cf7ff"}
]
box-shadow的语法
box-shadow: h-shadow v-shadow blur spread color inset;
注意:boxShadow 属性把一个或多个下拉阴影添加到框上。该属性是一个用逗号分隔阴影的列表,每个阴影由 2-4 个长度值、
一个可选的颜色值和一个可选的 inset 关键字来规定。省略长度的值是 0。值 说明
h-shadow 必需的。水平阴影的位置。允许负值
v-shadow 必需的。垂直阴影的位置。允许负值
blur 可选。模糊距离
spread 可选。阴影的大小
color 可选。阴影的颜色。在CSS颜色值寻找颜色值的完整列表
inset 可选。从外层的阴影(开始时)改变阴影内侧阴影
例如:看下面的效果是不是有那个味,还可以把盒子弄小点,比如高度为0
盒子高度为0的效果:
然后让盒子动起来,即通过定时更改盒子的颜色和位置即可做到 transition: all 1.2s linear;再加一个定时器setInterval()即可
代码如下:
<template><div style="height: 800px;background-color: pink; overflow: hidden"><div style="width:100px; height:0; margin: 200px auto; box-shadow: 0 0 135.25323349796668px 67.62661674898334px #5c9cff"></div></div></template><script>export default {name: '',data() {return {};},
};
</script><style lang="less" scoped>
</style>