JS+CSS radial-gradient 实现渐变中心随鼠标点击改变

HTML:

<div onclick="animationColor(this)">点&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;击</div>

CSS:

div {
  width: 320px;
  height: 80px;
  line-height: 80px;
  text-align: center;
  font-size: 40px;
  color: white;
  border-radius: 8px;
  box-shadow: 5px 5px 10px #888888;
  background-color: #017EFF;
  cursor: pointer;
}

JS:

function animationColor(obj) {
    // 最短总时长,在正中间点击时的时长,越向长边的两端,时长越短,最短为初始的一半
    // 总长度 / 步长 * 间隔 = 总时长,如果总长度不变,总时长随点击位置变化,那么步长越大,间隔越大
    // 间隔 = 总时长 / 总长度 / 步长
    // 获取鼠标点击的控件位置,也就是阴影的起始位置(百分比)
    const objRect = obj.getBoundingClientRect();
    const maxSide = objRect.width * 1.5; // 先写死宽是最宽边
    const x = Math.round((event.clientX - objRect.x) / objRect.width * 100); // (鼠标点击的位置 - 控件的位置) / 控件大小 * 100
    const y = Math.round((event.clientY - objRect.y) / objRect.height * 100); // (鼠标点击的位置 - 控件的位置) / 控件大小 * 100
    const beginOpacity = 0.7; //  点击透明的初始值
    const runTime = 300; // 效果运行总时长,值越小速度越快
    const step = 4; // 阴影扩大步长
    const offset = parseFloat((1 - Math.abs(50 - x) / 100).toFixed(1)); // 鼠标点击距中心的偏移量,50 表示中间,这里减去 x 是因为控件“宽”是最长边,如果控件“高”是最长边,你知道怎么做
    const totalTime = runTime * offset; // 距离中心越远速度越快,值越小
    const shadowRange = 20; // 弥散度,值越小弥散越明显
    const maxLength = maxSide / offset; // 阴影执行的最大长度,确保完全填充整个控件,需要根据点击的位置处理,离中心越远,此值越大
    const intervalTime = totalTime / (maxSide / step); //  setInterval 方法的第二个参数,重复执行行的间隔
    const totalRunTimes = maxLength / step; // 执行的总次数,透明度 opacity 还原时使用

    //  初始化一些要用到的值
    let size = 0; // 记录当前阴影大小
    obj.style.opacity = beginOpacity; //  初始透明度,从0开始太难看
    if (obj.intervalId === undefined) {
      obj.intervalId = 0; // setInterval 的返回值,停止时使用
    }
    if (obj.intervalId === 0) {
      obj.intervalId = setInterval(function() {
        obj.style.opacity = parseFloat(obj.style.opacity) + ((1- beginOpacity) / totalRunTimes);
        obj.style.backgroundImage = "radial-gradient(circle " + size + "px at " + x + "% " + y + "%, #017EFF " + shadowRange + "%, #2CDCB1)"; // 这里的50%是比较舒服的值,可以根据感觉修改
        size += step;
        if (size > maxLength) { // 这里总长度需要根据鼠标点击距中心的偏移量增加,这里用 objRect.width 也是因为 宽 是最长边
          clearInterval(obj.intervalId);
          obj.style.backgroundImage = "";
          obj.intervalId = 0;
          obj.style.opacity = 1;
        }
      }, intervalTime);
    } else {
      clearInterval(obj.intervalId);
      obj.style.backgroundImage = "";
      obj.intervalId = 0;
      obj.style.opacity = 1;
      animationColor(obj);
    }
}

 

上一篇:gradients(渐变)


下一篇:实现垂直布局的 8 种方式