为什么我的互动艺术不能像它应该在鼠标移动



我制作了一个交互式艺术,但不是缩放每个子像素,而是缩放每个子像素相同的px

p。注释掉的代码

const WIDTH = 512
const HEIGHT = 256
const ROWS = 8
const COLUMNS = 16
const container = document.querySelector('.container')
for (let rowIndex = 0; rowIndex < ROWS; rowIndex++) {
for (let colIndex = 0; colIndex < COLUMNS; colIndex++) {
let x = normalize(colIndex, 0, COLUMNS, 0, WIDTH) + 8
let y = normalize(rowIndex, 0, ROWS, 0, HEIGHT) + 8
if (document.querySelectorAll('.dot').length != 128) {
container.appendChild(circle(x, y))
}
}
}
window.addEventListener('mousemove', handleMouseMoveEvent)
const dots = Array.from(document.querySelectorAll('.dot'))
function handleMouseMoveEvent(event) {
const relativeMousePosition = {
x: event.clientX - container.getBoundingClientRect().left,
y: event.clientY - container.getBoundingClientRect().top,
}
for (let rowIndex = 0; rowIndex < ROWS; rowIndex++) {
for (let colIndex = 0; colIndex < COLUMNS; colIndex++) {
let x = normalize(colIndex, 0, COLUMNS, 0, WIDTH) + 8
let y = normalize(rowIndex, 0, ROWS, 0, HEIGHT) + 8
const deltaX = Math.abs(x - relativeMousePosition.x)
const deltaY = Math.abs(y - relativeMousePosition.y)
const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2)
let radius = normalize(distance, 0, 100, 2, 1)
radius = clamp(radius, 0, WIDTH)
for (let child = 0; child < dots.length; child++) {
dots[child].style.transform = `scale(${radius})`
}
}
}
}
function circle(x, y, radius = 16) {
const dot = document.createElement('div')
dot.className = 'dot'
dot.style.width = radius + 'px'
dot.style.height = radius + 'px'
dot.style.top = y + 'px'
dot.style.left = x + 'px'
return dot
}
function clamp(value, min = 0, max = 1) {
return Math.max(min, Math.min(max, value))
}
function normalize(number, currentScaleMin, currentScaleMax, newScaleMin = 0, newScaleMax = 1) {
const standardNormalization = (number - currentScaleMin) / (currentScaleMax - currentScaleMin)
return (newScaleMax - newScaleMin) * standardNormalization + newScaleMin
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
display: grid;
place-items: center;
background-color: #111;
}
.container {
position: relative;
width: 512px;
height: 256px;
box-shadow: 0 0 0 1px aquamarine; /* FOR DEBUGGING */
}
.dot {
position: absolute;
border-radius: 50%;
background-color: firebrick;
transition: transform 125ms ease, top 125ms ease, left 125ms ease;
}
<div class="container"></div>

p。S -我试图制作的动画最初是在canvas上创建的,并基于react。但我发现canvas相当模糊。请看这个链接,我正在尝试制作动画。

这不是我做这个动画的方式,但你所显示的代码本身有一些问题。你应该检查relativeMousePositionxy属性,当指针在.containerdiv内部时触发动画。此外,您还应该清空.container的内容。

我会告诉你一个快速修复,但你仍然需要在动画上工作。这不是一个真正的解决方案,而是一种为你指明正确方向的方法。

我建议使用CSStransitionwidthheight的圆圈上实现相同的结果,并使用display: nonevisibility: hidden而不是从DOM中添加和删除圆圈。

快速修复:

// clean up .container innerHTML
container.addEventListener('mouseleave', (e) => {
container.innerHTML = '';
});
function art(event) {
const relativeMousePosition = {
x: event.clientX - container.getBoundingClientRect().left,
y: event.clientY - container.getBoundingClientRect().top,
}
let isInsideContainer = relativeMousePosition.x > 0 && relativeMousePosition.x < 512 && relativeMousePosition.y > 0 && relativeMousePosition.y < 256;
// check the mouse position before triggering the animation
if(isInsideContainer) {
for (let rowIndex = 0; rowIndex < ROWS; rowIndex++) {
for (let colIndex = 0; colIndex < COLUMNS; colIndex++) {
let x = normalize(colIndex, 0, COLUMNS, 0, WIDTH) + 8
let y = normalize(rowIndex, 0, ROWS, 0, HEIGHT) + 8

const deltaX = Math.abs(x - relativeMousePosition.x)
const deltaY = Math.abs(y - relativeMousePosition.y)

const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2)

let radius = normalize(distance, 0, 100, 32, 1)
radius = clamp(radius, 0, WIDTH)

container.appendChild(dot(x, y, radius))
}
}
}
}

在Kunal的评论之后,我添加了一个更详细的可能解决方案。这只是一个解决方案,你可能会找到其他方法来达到同样的结果,但这可能是一个好的开始。

const WIDTH = 512
const HEIGHT = 256
const ROWS = 8
const COLUMNS = 16
const PROXIMITY_THRESHOLD = Number.parseInt(WIDTH / 6, 10);
// A circle object
// represent an element in the DOM
class Circle {
constructor(position, id) {
this.position = position;
this.id = id;
}
distanceFrom(xCoordinate, yCoordinate) {
const deltaX = Math.abs(this.position.x - xCoordinate);
const deltaY = Math.abs(this.position.y - yCoordinate);
const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2)
return distance;
}
isInProximity(distance) {
return distance <= PROXIMITY_THRESHOLD;
}
}
const createCircleRow = () => {
return new Array(COLUMNS)
.fill(null)
.map(() =>  new Circle());
};
// We create an array of arrays of circles object
const circles = new Array(ROWS).fill(null).map(createCircleRow);
const container = document.querySelector('.container')
for (let rowIndex = 0; rowIndex < ROWS; rowIndex++) {
for (let colIndex = 0; colIndex < COLUMNS; colIndex++) {
let x = normalize(colIndex, 0, COLUMNS, 0, WIDTH) + 8
let y = normalize(rowIndex, 0, ROWS, 0, HEIGHT) + 8
// Set the position and the id properties for circle object in circles Array
circles[rowIndex][colIndex].position = {x, y};
let id = `${rowIndex},${colIndex}`;
circles[rowIndex][colIndex].id = id;
if (document.querySelectorAll('.dot').length != 128) {
let circleElement = circle(x, y)
// Add an id to the circle Element
circleElement.setAttribute('id', id);
container.appendChild(circleElement);
}
}
}
function animateByPosition(xPosition, yPosition) {
circles.forEach((row) => {
row.forEach((circle) => {
let circleElement = document.getElementById(circle.id);
let distance = circle.distanceFrom(xPosition, yPosition);
if(circle.isInProximity(distance)) {
circleElement.style.visibility = 'visible';
let scaleAmount = 2 * (distance/PROXIMITY_THRESHOLD);
circleElement.style.transform = `scale(${scaleAmount})`;
} else {
circleElement.style.transform = null;
circleElement.style.visibility = 'hidden';
}
});
});
}
function hideCircles() {
circles.forEach((row) => {
row.forEach((circle) => {
let circleElement = document.getElementById(circle.id);
circleElement.style.transform = null;
circleElement.style.visibility = 'hidden';
});
});
}
window.addEventListener('mousemove', handleMouseMoveEvent);
container.addEventListener('mouseleave', hideCircles);
function handleMouseMoveEvent(event) {
const relativeMousePosition = {
x: event.clientX - container.getBoundingClientRect().left,
y: event.clientY - container.getBoundingClientRect().top,
}
let isInsideContainer = relativeMousePosition.x > 0 && relativeMousePosition.x < 512 && relativeMousePosition.y > 0 && relativeMousePosition.y < 256;
// check the mouse position before triggering the animation
if(isInsideContainer) {
animateByPosition(relativeMousePosition.x, relativeMousePosition.y);
}
}
function circle(x, y, radius = 16) {
const dot = document.createElement('div')
dot.className = 'dot'
dot.style.width = radius + 'px'
dot.style.height = radius + 'px'
dot.style.top = y + 'px'
dot.style.left = x + 'px'
return dot
}
function normalize(number, currentScaleMin, currentScaleMax, newScaleMin = 0, newScaleMax = 1) {
const standardNormalization = (number - currentScaleMin) / (currentScaleMax - currentScaleMin)
return (newScaleMax - newScaleMin) * standardNormalization + newScaleMin
}
.dot {
position: absolute;
border-radius: 50%;
background-color: firebrick;
visibility: hidden;
transition: transform 0.5s;
}

相关内容

  • 没有找到相关文章

最新更新