CSS/SVG/Canvas:动态/移动渐变

问题描述 投票:0回答:1

我正在研究如何创建一个具有动态/移动背景的 div,基于具有三种颜色的径向渐变:

我们的想法是有一个像这样的中心点:

拖动动画并以或多或少随机的方式混合颜色。

我尝试搜索如何使用 CSS 实现此目的,但我能找到的只是简单的静态径向示例。解决这个问题的最佳方法是什么?

css svg html5-canvas gradient
1个回答
0
投票

第一步是弄清楚如何制作其中一个。然后你可以旋转它或其他什么。我发现它看起来像一个色轮。我改编了代码https://stackoverflow.com/a/39399649/3807365

  1. 当您远离螺旋效果的中心时,我会向色调添加偏移量
  2. 我已将鼠标位置纳入中心的计算中。
  3. 这是您可以进一步调整它的开始。

var mx = 0
var my = 0
var diameter = 200
var wheel
var can
var ctx

main()


function newEl(tag) {
  return document.createElement(tag)
}


function main() {
  wheel = makeWheel(diameter);
  wheel.addEventListener('mousemove', moveCenter);
  document.body.appendChild(wheel);
}


function hsv2rgb(hsv) {
  var h = hsv.hue,
    s = hsv.sat,
    v = hsv.val;
  var rgb, i, data = [];
  if (s === 0) {
    rgb = [v, v, v];
  } else {
    h = h / 60;
    i = Math.floor(h);
    data = [v * (1 - s), v * (1 - s * (h - i)), v * (1 - s * (1 - (h - i)))];
    switch (i) {
      case 0:
        rgb = [v, data[2], data[0]];
        break;
      case 1:
        rgb = [data[1], v, data[0]];
        break;
      case 2:
        rgb = [data[0], v, data[2]];
        break;
      case 3:
        rgb = [data[0], data[1], v];
        break;
      case 4:
        rgb = [data[2], data[0], v];
        break;
      default:
        rgb = [v, data[0], data[1]];
        break;
    }
  }
  return rgb;
};

function clamp(min, max, val) {
  if (val < min) return min;
  if (val > max) return max;
  return val;
}



function drawWheel(ctx) {
  ctx.clearRect(0, 0, can.width, can.height);

  var imgData = ctx.getImageData(0, 0, diameter, diameter);
  var maxRange = diameter / 2;

  for (var y = 0; y < diameter; y++) {
    for (var x = 0; x < diameter; x++) {
      var xPos = x - (diameter / 2) - mx;
      var yPos = (diameter - y) - (diameter / 2) - my;

      var polar = pos2polar({
        x: xPos,
        y: yPos
      });

      var hueOffset = 50 * (polar.len / maxRange); 

      var hue = polar.ang + hueOffset;

      hue = hue % 360;
      while (hue < 0) {
        hue += 360;
      }

      var sat = clamp(0, 1, polar.len / (maxRange / 2));
      var val = clamp(0, 1, (maxRange - polar.len) / (maxRange / 2));

      var rgb = hsv2rgb({
        hue: hue,
        sat: sat,
        val: val
      });

      var index = 4 * (x + y * diameter);
      imgData.data[index + 0] = rgb[0] * 255;
      imgData.data[index + 1] = rgb[1] * 255;
      imgData.data[index + 2] = rgb[2] * 255;
      imgData.data[index + 3] = 255;
    }
  }
  ctx.putImageData(imgData, 0, 0);
}

function makeWheel(diameter) {
  can = newEl('canvas');
  ctx = can.getContext('2d');
  can.width = diameter;
  can.height = diameter;

  drawWheel(ctx)
  return can;
}

function deg2rad(deg) {
  return (deg / 360) * (2 * Math.PI);
}

function rad2deg(rad) {
  return (rad / (Math.PI * 2)) * 360;
}

function pos2polar(inPos) {
  var vecLen = Math.sqrt((inPos.x + mx) * (inPos.x + mx) + (inPos.y + my) * (inPos.y + my));
  var something = Math.atan2(inPos.y, inPos.x);
  while (something < 0)
    something += 2 * Math.PI;

  return {
    ang: rad2deg(something),
    len: vecLen
  };
}



function moveCenter(event) {
  var color = document.getElementById('color');

  mx = -diameter / 2 + event.offsetX;
  my = -1 * (-diameter / 2 + event.offsetY);

  color.innerText = "" + mx + ", " + my

}

function loop() {
  drawWheel(ctx)
  requestAnimationFrame(loop)
}
loop()
canvas {
  border: solid 1px red;
}
<div id="color" style="width: 200px; height: 50px; float: left;">Move mouse</div>

© www.soinside.com 2019 - 2024. All rights reserved.