canvas实现鼠标点线跟随交互效果代码

代码语言:html

所属分类:其他

代码描述:canvas实现鼠标点线跟随交互效果代码

代码标签: canvas 鼠标 点线 跟随 交互

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  


  
  
<style>
/*
global
*/
*, *::before, *::after {
		margin: 0;
		padding: 0;
		border: 0;
		box-sizing: border-box;
}

*:focus {
		outline: none;
}

body {
		display: flex;
		align-items: center;
		justify-content: center;
		height: 100vh;
		background: radial-gradient(#333333, #000000);
		overflow: hidden;
}

canvas {
		touch-action: none;
}
</style>

  
  
  
</head>

<body translate="no">
  
  
      <script >
//---

'use strict';

//---

console.clear();

//---

let w = 0;
let h = 0;

let animationFrame = null;
let isTouchDevice = false;

const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

let imageData = null;
let data = null;

const center = { x: w / 2, y: h / 2 };
const border = { left: 1, top: 1, right: w, bottom: h };

let pointerPos = { x: center.x, y: center.y };
let pointerDown = false;
let pointerMoveTimeout;

const pointerMoveTimeoutTime = 2500;

//---

const dotColorR = 25;
const dotColorG = 155;
const dotColorB = 200;
const dotColorA = 255;
const dotsRadius = 4;
const dotsDistance = 10;
const dotsDiameter = dotsRadius * 2;
const dotsSpeed = 10;
const dotsWobbleFactor = 0.95;
const dotsWobbleSpeed = 0.05;
const dotsMaxEscapeRouteLengthBasis = 100;
let dotsMaxEscapeRouteLength = 100;
const dotsMouseDistanceSensitivitySpeed = 5;
const dotsMouseDistanceSensitivityMax = 250;
const dotsMouseDistanceSensitivityMinBasis = 100;
let dotsMouseDistanceSensitivityMin = 100;
let dotsMouseDistanceSensitivity = dotsMouseDistanceSensitivityMin;
let dotsHolder = [];
let dotsCount = 0;

let introPath = [];
let introInterval = null;
let introIndex = 0;
let introPathCoordinatesCount = 256;
let introSpeedBasis = 10;
let introSpeed = introSpeedBasis;

//---

function init() {

  isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;

  //---

  if (isTouchDevice === true) {

    canvas.addEventListener('touchmove', cursorMoveHandler, false);
    canvas.addEventListener('touchend', cursorLeaveHandler, false);
    canvas.addEventListener('touchcancel ', cursorLeaveHandler, false);

  } else {

    canvas.addEventListener('pointermove', cursorMoveHandler, false);
    canvas.addEventListener('pointerdown', cursorDownHandler, false);
    canvas.addEventListener('pointerup', cursorUpHandler, false);
    canvas.addEventListener('pointerleave', cursorLeaveHandler, false);

  }

  //---

  document.body.appendChild(canvas);

  window.addEventListener('resize', onResize, false);

  restart();

}

function onResize(event) {

  restart();

}

function restart() {

  const innerWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  const innerHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

  //---

  w = innerWidth;
  h = innerHeight;

  //---

  canvas.width = w;
  canvas.height = h;

  imageData = context.getImageData(0, 0, w, h);
  data = imageData.data;

  //---

  center.x = w / 2;
  center.y = h / 2;

  pointerPos.x = -10000;
  pointerPos.y = -10000;

  border.right = w;
  border.bottom = h;

  //---

  removeDots();
  addDots();

  //---

  if (animationFrame != null) {

    cancelAnimFrame(animationFrame);

  }

  render();

  //---

  initIntroPath(introPathCoordinatesCount);
  stopIntro();
  playIntro();

}

//---

function addDots() {

  const dotsPerRow = Math.floor(w / (dotsDiameter + dotsDistance)) + dotsDiameter * 2;
  const dotsPerColumn = Math.floor(h / (dotsDiameter + dotsDistance)) + dotsDiameter * 2;
  const dotsCount = dotsPerRow * dotsPerColumn;

  const xs = -dotsDiameter;
  const ys = -dotsDiameter;

  let dotIndex = 0;

  for (let i = 0; i < dotsPerColumn; i++) {

    for (let j = 0; j < dotsPerRow; j++) {

      const x = xs + j * (dotsDistance + dotsDiameter);
      const y = ys + i * (dotsDistance + dotsDiameter);

      const dot = addDot(x, y, dotsRadius, dotsDiameter, dotColorR, dotColorG, dotColorB, dotColorA);

      dot.neighborRightIndex = j < dotsPerRow - 1 ? dotIndex + 1 : -1;
      dot.neighborBottomIndex = i < dotsPerColumn - 1 ? dotIndex + dotsPerRow : -1;

      dotsHolder.push(dot);
      dotIndex++;

    }

  }

  for (let i = 0, l = dotsHolder.length; i < l; i++) {

    const dot = dotsHolder[i];

    if (dot.neighborRightIndex > -1) {

      dot.neighborRight = dotsHolder[dot.neighborRightIndex];

    }

    if (dot.neighborBottomIndex > -1) {

      dot.neighborBottom = dotsHolder[dot.neighborBottomIndex];

    }

  }

}

function addDot(x, y, radius, diameter, r, g, b, a) {

  const dot = {};

  dot.cx = x;
  dot.cy = y;
  dot.x = x;
  dot.y = y;
  dot.sx = 0;
  dot.sy = 0;
  dot.radius = radius;
  dot.r = radius;
  dot.minRadius = radius * 0.75;
  dot.maxRadius = radius * 2.5;
  dot.diameter = diameter;
  dot.color = {};
  dot.color.r = r;
  dot.color.g = g;
  dot.color.b = b;
  dot.color.a = a;
  dot.colorDark = {};
  dot.colorDark.r = Math.floor(r * 0.75);
  dot.colorDark.g = Math.floor(g * 0.75);
  dot.colorDark.b = Math.floor(b * 0.75);
  dot.colorDark.a = Math.floor(a * 0.5);
  dot.colorDraw = {};
  dot.colorDraw.r = r;
  dot.colorDraw.g = g;
  dot.colorDraw.b = b;
  dot.colorDraw.a = a;
  dot.activeTime = 0;
  dot.distance = 0;
  dot.neighborRightIndex = 0;
  dot.neighborBottomIndex = 0;
  dot.neighborRight = null;
  dot.neighborBottom = null;

  return dot;

}

function removeDots() {

  if (dotsHolder.length > 0) {

    dotsHolder = [];

  }

}

//---

function initIntroPath(numPoints) {

  introPath = [];

  const radiusX = w / 4;
  const radiusY = h / 3;
  const centerX = w / 2;
  const centerY = h / 2;

  for (let i = 0; i < numPoints; i++) {

    const angle = i / numPoints * 2 * Math.PI;
    const x = centerX + radiusX * Math.cos(angle);
    const y = centerY + radiusY * Math.sin(2 * angle) / 2;

    introPath.push({ x, y });

  }

}

function playIntro() {

  introInterval = setInterval(() => {

    const pos = introPath[introIndex];

    pointerPos = pos;

    introIndex++;

    if (introIndex >= introPath.length - 1) {

      introIndex = 0;

    }

  }, introSpeed);

}

function stopIntro() {

  clearTimeout(pointerMoveTimeout);

  if (introInterval !== null) {

    clearInterval(introInterval);

    introInterval = null;

  }

}

//---

function cursorDownHandler(event) {

  pointerDown = true;

}

function cursorUpHandler(event) {

  pointerDown = false;

}

function cursorLeaveHandler(event) {

  pointerPos = { x: -10000, y:.........完整代码请登录后点击上方下载按钮下载查看

网友评论0