Js-动态边框

<!DOCTYPE html>
<html>
<head>
	<title></title>
	<meta charset="utf-8">
	<style type="text/css">
	*{
		margin: 0;
		padding: 0;
	}
	body {
		flex-wrap:wrap;
		flex:1
	}
	.flex {
		display:flex;
		justify-content:center;
		align-items:center;
	}
	.demo {
		width:550px;
		height:200px;
		position:relative;
		margin:50px;
		background:linear-gradient(90deg,#feac5e,#c779d0,#4bc0c8);
		color:#fff;
		font-size:30px;
	}
	.circle {
		width:100px;
		height:100px;
		border-radius:50%;
		position:relative;
		background:linear-gradient(90deg,#feac5e,#c779d0,#4bc0c8);
		color:#fff;
	}
	.circle:before {
		content:'';
		position:absolute;
		left:0;
		top:0;
		right:0;
		bottom:0;
		margin:-6px;
		border:5px solid transparent;
		border-top:5px solid #f64f59;
		border-radius:50%;
		transform:rotate(45deg);
		animation:circleRotate 3s linear infinite;
	}
	@keyframes circleRotate {
		0% {
			transform:rotate(0);
		}
		100% {
			transform:rotate(360deg);
		}
	}
</style>
</head>
<body>
	<div class="demo flex"> ^-^正常的边框</div>
	<div class="demo flex">^-^更慢的边框</div>
	<div class="demo flex">^-^更快的边框</div>
	<div class="demo flex">^-^图片边框</div>
	<div class="demo flex">^-^更细的边框</div>
	<div class="flex circle">附赠的圆形</div>
	<script type="text/javascript">
	/* 
功能:为矩形元素附上一层运动的边线
原理:  核心:css clip rect   web animation 负责动态化
注意:请使用较高版本现代浏览器打开  本代码 使用了es6语法 且并未对css各浏览器前缀做处理
    如需兼容低版本浏览器   请自行加 web animate polyfill 及 使用babel转译

*/


/* 使用
_initDanceBorder(el,option);
*/

//纯 JS实现动态边框效果
//根据 http://www.jq22.com/jquery-info3297 bee木头 作者 核心思路(css clip rect) 创作
//传入依赖元素 自动生成动态边框

/* 
测试用配置
*/
const options = [{}, {
	duration: 12000,
	double: false
}, {
	duration: 4000,
	'border-color': 'red',
	'easing': 'ease-in-out'
}, {
	'margin': -15,
	'borderWidth': 10,
	'border-image': "url(./wx.png) 10 10",

}, {
	'borderWidth': 2
}]


//使用方法
for (let i = 0; i < document.getElementsByClassName('demo').length; i++) {
	_initDanceBorder(document.getElementsByClassName('demo')[i], options[i]);
}

/***************************      主 体 代 码       ********************************/

//传入dom元素与 配置即可
function _initDanceBorder(el, options = {}) {
    //默认设置  尺寸单位均为px
    let _options = {
        //边框模糊度  
        blur: 1,
        //距依赖元素距离 
        margin: -5,
        //边框宽度  
        borderWidth: 4,
        //转一周时长  
        duration: 8000,
        //运动效果  default:匀速
        easing: 'linear',
        //是否两条运动线  默认两条
        double: true,
        //渐变色边框 优先级高  若使用渐变色或图片背景  请正确传入该值  否则边框不会显示
        'border-image': 'linear-gradient(to bottom right, #12c2e9,#c471ed,#f64f59) 10 10',
        //边框色   border-image 优先级低
        'border-color': 'green'
    }

    //存在正常色 不存在渐变色   渐变色赋值为空
    options['border-color'] && !options['border-image'] && (_options['border-image'] = 'none')
    //设置拷贝
    Object.keys(_options).forEach(key => {
    	options[key] && (_options[key] = options[key]);
        //double 的特殊判断
        if (key == 'double' && typeof options[key] == 'boolean') {
        	_options[key] = options[key]
        }
    })

    //元素基本属性
    const styleObj = {
    	'content': '',
    	'z-index': -1,
    	'margin': `${_options.margin}px`,
    	'border': `${_options.borderWidth}px solid`,
    	'border-color': _options['border-color'],
    	'border-image': _options['border-image'],
    	'filter': `blur(${_options.blur}px)`,
    	'position': 'absolute',
    	'top': 0,
    	'bottom': 0,
    	'left': 0,
    	'right': 0
    }

    const pW = el.style.width || el.offsetWidth;
    const pH = el.style.height || el.offsetHeight;

    const fullWidth = pW + _options.margin * -2;
    const fullHeight = pH + _options.margin * -2;

    //四边切割数组
    const rectArray = [
    `rect(${-_options.blur}px, ${fullWidth}px, ${-_options.margin}px, ${-_options.blur}px)`,
    `rect(0px, ${-_options.margin}px, ${fullHeight + _options.blur}px, ${-_options.blur}px)`,
    `rect(${pH}px, ${fullWidth + _options.blur}px, ${fullHeight + _options.blur}px, 0px)`,
    `rect(${-_options.blur}px, ${fullWidth + _options.blur}px, ${fullHeight}px, ${pW + _options.blur}px)`
    ]

    const clipAnimate = [{
    	clip: rectArray[0]
    },
    {
    	clip: rectArray[1],
    	offset: 0.25
    },
    {
    	clip: rectArray[2],
    	offset: 0.5
    },
    {
    	clip: rectArray[3],
    	offset: 0.75
    },
    {
    	clip: rectArray[0],
    	offset: 1
    }
    ];

    //由于border的可见特性使delay无效  第二条延迟一半的边动画   从0.5开始  
    const clipAnimateTwo = [{
    	clip: rectArray[2]
    },
    {
    	clip: rectArray[3],
    	offset: 0.25
    },
    {
    	clip: rectArray[0],
    	offset: 0.5
    },
    {
    	clip: rectArray[1],
    	offset: 0.75
    },
    {
    	clip: rectArray[2],
    	offset: 1
    }
    ];

    const animateOption = {
    	duration: _options.duration,
    	iterations: Infinity,
    	easing: _options.easing
    };

    const section = initBaseEl();

    //Web Animations  实现keyframes动画
    section.animate(clipAnimate, animateOption);

    //是否两条运动线
    if (_options.double) {
    	let sectionTwo = initBaseEl();
    	sectionTwo.animate(clipAnimateTwo, animateOption);
    }

    //构造元素
    function initBaseEl() {
    	const section = document.createElement("section");
        //style属性赋值
        Object.keys(styleObj).forEach(key => {
        	section.style[key] = styleObj[key]
        })

        el.appendChild(section);

        return section;
    }


    //页面尺寸改变  修改
}
</script>
</body>
</html>

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值