gpt4 book ai didi

javascript - 向 d3.drag() 行为添加过渡

转载 作者:行者123 更新时间:2023-12-04 08:55:15 25 4
gpt4 key购买 nike

我即将用 d3.js 完成我的第一个项目。它计算滑雪者可用的势能,如果所有这些能量都转换为动能,我想计算滑雪者的预期速度。我想要的最后一件事是在滑雪者掉落时为他添加过渡。我希望滑雪者始终过渡到右侧的黑色圆圈 (p2)。过渡的持续时间现在并不重要。有没有简单的方法来完成这项任务?
example

const height = 500;
const width = 800;
const skierIconSvg = 'https://image.flaticon.com/icons/svg/94/94150.svg';
const gate =
'https://docs.google.com/drawings/d/1k-mtzjW05U6KZKNt0kAI2pWqKsXFobptsa9kz6grYzA/edit?usp=sharing';

const [p1, p2, p3] = [
[80, 130],
[600, 170],
[750, 190],
];

const svg = d3.select('svg');

// Store a reference to the span we're going to update
const skierHeight = d3.select('#skier-height');

const vek = document.querySelector('#vekt');
console.log(vek.value);

const line = svg.append('line').attr('stroke', 'black');

const connection = svg.append('line').attr('stroke', 'green');

const projection = svg
.append('circle')
.attr('r', 5)
.attr('stroke', 'red')
.attr('fill', 'none');

const g = svg
.append('g')
.attr('cursor', 'move')
.attr('pointer-events', 'all')
.attr('stroke', 'transparent')
.attr('stroke-width', 30);

const point = g
.selectAll('image')
.data([p1, p2])
.enter()
.append('circle')
.attr('r', 10)
.call(
d3
.drag()
.subject(([x, y]) => ({
x,
y,
}))
.on('drag', dragged)
);

const skier = g
.append('image')
.attr('id', 'skier')
.datum(p3)
.attr('href', skierIconSvg)
.attr('width', 100)
.attr('height', 100)
.attr('transform', 'translate(-50, -40)')
.call(
d3
.drag()
.subject(([x, y]) => ({
x,
y,
}))
.on('drag', dragged)
);

update();

function dragged(d) {
d[0] = d3.event.x;
d[1] = d3.event.y;
update();
potensiellEnergi();
}

function update() {
const t = (width + height) / distance(p1, p2);

const l1 = interpolate(p1, p2, t);

const l2 = interpolate(p2, p1, t);
const p = interpolate(p1, p2, project(p1, p2, p3));

connection.attr('x1', p3[0]).attr('y1', p3[1]);
connection.attr('x2', p[0]).attr('y2', p[1]);
projection.attr('cx', p[0]).attr('cy', p[1]);
line.attr('x1', l1[0]).attr('y1', l1[1]);
line.attr('x2', l2[0]).attr('y2', l2[1]);
point.attr('cx', (d) => d[0]).attr('cy', (d) => d[1]);
skier.attr('x', (d) => d[0]).attr('y', (d) => d[1]);

skierHeight.text(`${getHeight(p, p1, p2).toFixed(2)} meter`);
}

function distance([x1, y1], [x2, y2]) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}

function interpolate([x1, y1], [x2, y2], t) {
return [x1 + (x2 - x1) * t, y1 + (y2 - y1) * t];
}

function project([x1, y1], [x2, y2], [x3, y3]) {
const x21 = x2 - x1,
y21 = y2 - y1;
const x31 = x3 - x1,
y31 = y3 - y1;
return (x31 * x21 + y31 * y21) / (x21 * x21 + y21 * y21);
}

function getHeight([xp, yp], [x1, y1], [x2, y2]) {
// Note that y is counted from top to bottom, so higher y means
// a point is actually lower.

// First, the total height is 100 metres.
const pxPerMeter = (y2 - y1) / 100;

// Calculate the height diff in pixels
const heightDiffPx = y2 - yp;

// Now transform it to meters
return heightDiffPx / pxPerMeter;
}

function vektVelger() {
const vektVerdi = document.querySelector('#vekt');
const vektDisplay = document.querySelector('#skier-vekt');

vektDisplay.innerHTML = vektVerdi.value;
}

function potensiellEnergi() {
const vektVerdi = parseInt(document.querySelector('#skier-vekt').textContent);
const skierHeight = parseInt(
document.querySelector('#skier-height').textContent
);
const potEDisplay = document.querySelector('#skier-potentialenergi');
const potEnergi = `${vektVerdi * skierHeight * 9.8}`;
return (potEDisplay.innerHTML = `${potEnergi}`);
}
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://d3js.org/d3-path.v1.min.js"></script>
<script src="https://d3js.org/d3-shape.v1.min.js"></script>
<script src="https://d3js.org/d3-scale.v3.min.js"></script>
<script src="https://d3js.org/d3-axis.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-selection.v1.min.js"></script>

<link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@300&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap" rel="stylesheet" />
</head>

<body>
<h1>Forsøk på å lage en tutorial i JavaScript og D3.js</h1>
<h2>Høydeforskjell: <span id="skier-height"></span></h2>
<h2>Vekt: <span id="skier-vekt">70</span> kg</h2>
<h2>
Gravitasjonskraft (fg): <span id="skier-gravitasjon">9.8</span> m/sek/sek
</h2>
<h2>Potential Energy: <span id="skier-potentialenergi">0</span> KJOULE</h2>

<svg width="800" height="300"></svg>
<form>
Velg utøverens vekt:
<input type="number" id="vekt" placeholder="Velg utøverens vekt" />
</form>
<input type="button" value="velg" onclick="vektVelger()" />

<script src="skier.js"></script>
</body>

</html>

最佳答案

我在下面添加了过渡。滑雪者首先下降到地面,当过渡完成后,他们滑到最后。你甚至可以使用 one of these过渡缓动方法,使它们在此过程中获得速度!
我在处理您的包裹时遇到了一些问题。我不明白为什么你的 HTML 中有所有这些行,但它们破坏了 d3.transition:

  <script src="https://d3js.org/d3-path.v1.min.js"></script>
<script src="https://d3js.org/d3-shape.v1.min.js"></script>
<script src="https://d3js.org/d3-scale.v3.min.js"></script>
<script src="https://d3js.org/d3-axis.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-selection.v1.min.js"></script>
删除所有这些,只留下 <script src="https://d3js.org/d3.v5.js"></script>完全没问题。

const height = 500;
const width = 800;
const skierIconSvg = 'https://image.flaticon.com/icons/svg/94/94150.svg';
const gate =
'https://docs.google.com/drawings/d/1k-mtzjW05U6KZKNt0kAI2pWqKsXFobptsa9kz6grYzA/edit?usp=sharing';

const [p1, p2, p3] = [
[80, 130],
[600, 170],
[750, 190],
];

const svg = d3.select('svg');

// Store a reference to the span we're going to update
const skierHeight = d3.select('#skier-height');

const vek = document.querySelector('#vekt');
console.log(vek.value);

const line = svg.append('line').attr('stroke', 'black');

const connection = svg.append('line').attr('stroke', 'green');

const projection = svg
.append('circle')
.attr('r', 5)
.attr('stroke', 'red')
.attr('fill', 'none');

const g = svg
.append('g')
.attr('cursor', 'move')
.attr('pointer-events', 'all')
.attr('stroke', 'transparent')
.attr('stroke-width', 30);

const point = g
.selectAll('image')
.data([p1, p2])
.enter()
.append('circle')
.attr('r', 10)
.call(
d3
.drag()
.subject(([x, y]) => ({
x,
y,
}))
.on('start', () => {
// Interrupt all transitions
skier.interrupt();
connection.interrupt();

// Update the value of p3 to wherever the skier happened to be
// This will stop him dead in his tracks instead of snapping him back to the old position
p3[0] = Number(skier.attr('x'));
p3[1] = Number(skier.attr('y'));
})
.on('drag', dragged)
);

const skier = g
.append('image')
.attr('id', 'skier')
.datum(p3)
.attr('href', skierIconSvg)
.attr('width', 100)
.attr('height', 100)
.attr('transform', 'translate(-50, -40)')
.call(
d3
.drag()
.subject(() => ({
// Use where the skier is, not where he's supposed to be
x: Number(skier.attr('x')),
y: Number(skier.attr('y')),
}))
.on('start', () => {
// Interrupt all transitions
skier.interrupt();
connection.interrupt();
})
.on('drag', dragged)
.on('end', dropSkier)
);

update();

function dragged(d) {
d[0] = d3.event.x;
d[1] = d3.event.y;
update();
potensiellEnergi();
}

function update() {
const t = (width + height) / distance(p1, p2);

const l1 = interpolate(p1, p2, t);

const l2 = interpolate(p2, p1, t);
const p = interpolate(p1, p2, project(p1, p2, p3));

connection.attr('x1', p3[0]).attr('y1', p3[1]);
connection.attr('x2', p[0]).attr('y2', p[1]);
projection.attr('cx', p[0]).attr('cy', p[1]);
line.attr('x1', l1[0]).attr('y1', l1[1]);
line.attr('x2', l2[0]).attr('y2', l2[1]);
point.attr('cx', (d) => d[0]).attr('cy', (d) => d[1]);
skier.attr('x', (d) => d[0]).attr('y', (d) => d[1]);

skierHeight.text(`${getHeight(p, p1, p2).toFixed(2)} meter`);
}
function distance([x1, y1], [x2, y2]) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}

function interpolate([x1, y1], [x2, y2], t) {
return [x1 + (x2 - x1) * t, y1 + (y2 - y1) * t];
}

function project([x1, y1], [x2, y2], [x3, y3]) {
const x21 = x2 - x1,
y21 = y2 - y1;
const x31 = x3 - x1,
y31 = y3 - y1;
return (x31 * x21 + y31 * y21) / (x21 * x21 + y21 * y21);
}

function getHeight([xp, yp], [x1, y1], [x2, y2]) {
// Note that y is counted from top to bottom, so higher y means
// a point is actually lower.

// First, the total height is 100 metres.
const pxPerMeter = (y2 - y1) / 100;

// Calculate the height diff in pixels
const heightDiffPx = y2 - yp;

// Now transform it to meters
return heightDiffPx / pxPerMeter;
}

function vektVelger() {
const vektVerdi = document.querySelector('#vekt');
const vektDisplay = document.querySelector('#skier-vekt');

vektDisplay.innerHTML = vektVerdi.value;
}

function potensiellEnergi() {
const vektVerdi = parseInt(document.querySelector('#skier-vekt').textContent);
const skierHeight = parseInt(
document.querySelector('#skier-height').textContent
);
const potEDisplay = document.querySelector('#skier-potentialenergi');
const potEnergi = `${vektVerdi * skierHeight * 9.8}`;
return (potEDisplay.innerHTML = `${potEnergi}`);
}

function dropSkier(d) {
const projection = interpolate(p1, p2, project(p1, p2, p3));
skier
.transition()
.duration(500)
// First down to the ground
.attr('x', projection[0])
.attr('y', projection[1])
.on("end", () => {
skier
.transition()
.duration(2500)
// First down to the ground
.attr('x', p2[0])
.attr('y', p2[1]);
});

// Remove the line together with the skier
connection
.transition()
.duration(500)
// First down to the ground
.attr('x1', projection[0])
.attr('y1', projection[1]);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v5.js"></script>

<link
href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@300&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap"
rel="stylesheet"
/>
</head>

<body>
<h1>Forsøk på å lage en tutorial i JavaScript og D3.js</h1>
<h2>Høydeforskjell: <span id="skier-height"></span></h2>
<h2>Vekt: <span id="skier-vekt">70</span> kg</h2>
<h2>
Gravitasjonskraft (fg): <span id="skier-gravitasjon">9.8</span> m/sek/sek
</h2>
<h2>Potential Energy: <span id="skier-potentialenergi">0</span> KJOULE</h2>

<svg width="800" height="300"></svg>
<form>
Velg utøverens vekt:
<input type="number" id="vekt" placeholder="Velg utøverens vekt" />
</form>
<input type="button" value="velg" onclick="vektVelger()" />

<script src="skier.js"></script>
</body>
</html>

关于javascript - 向 d3.drag() 行为添加过渡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63859153/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com