svelte 中可拖动的 d3 世界地球仪
我有下一个问题,我正在尝试在 svelte 应用程序中使用 d3 创建一个可拖动的世界地球仪,我遇到的问题是当尝试拖动地球仪时,拖动操作很滞后我认为我的问题与可拖动组件中的内存泄漏我不知道这是否是这种滞后行为的主要原因。地球仪是用 svg 绘制的,
这是应用程序链接: https://codesandbox.io/s/cocky-benz-2mk5bs
可拖动组件
<script>
import { onMount, onDestroy, afterUpdate } from 'svelte';
import { mouseAdjusted } from '../lib/Utilities';
onMount(() => console.log('mounted'));
afterUpdate(() => {
//console.log('Destroyed');
});
export let mouseX;
export let mouseY;
let offset;
let isMove = false;
const start = (e) => {
isMove = true;
const element = e.target;
const target = e.target.parentElement.parentElement.getScreenCTM();
// get the mouse position in the svg shape
offset = mouseAdjusted(e.clientX, e.clientY, target);
// rest the shape mouse posicion from the shape x y coordinates
offset[1] -= +element.getAttributeNS(null, 'y');
offset[0] -= +element.getAttributeNS(null, 'x');
};
const move = (e) => {
if (isMove) {
const target = e.target.parentElement.parentElement.getScreenCTM();
const [x, y] = mouseAdjusted(e.clientX, e.clientY, target);
mouseX = offset[0] - x;
mouseY = offset[1] - y;
}
};
const end = () => {
isMove = false;
offset = null;
};
</script>
<svelte:window
on:mousemove|preventDefault|stopPropagation={move}
on:mouseup|preventDefault|stopPropagation={end}
/>
<g class="draggable" on:mousedown|preventDefault|stopPropagation={start}>
<slot />
</g>
图形组件
<script>
import { onMount, onDestroy } from "svelte";
import * as d3 from "d3";
import * as topojson from "topojson-client";
import Draggable from "./draggable.svelte";
let width = 500;
$: width = width * 0.95;
let height = 500;
$: height = height * 0.98;
let world;
let x;
let y;
let projection;
let path;
let ROTATION = [-45, -65, 0];
// Add topojsom
onMount(async () => {
const resp = await d3.json(
"/src/assets/world-administrative-boundaries.json"
);
world = await topojson.feature(resp, "world-administrative-boundaries");
});
$: ROTATION = [-x, y, 0];
$: projection = d3
.geoOrthographic()
.fitSize([width, height], world)
.scale([width / 3])
.rotate(ROTATION);
$: path = d3.geoPath(projection);
const fillScale = d3
.scaleOrdinal()
.domain(["", ""])
.range([" hsl(40, 98%, 47%)", "hsl(9, 64%, 50%)"])
.unknown("hsl(227, 16%, 42%)");
const strokeScale = d3
.scaleOrdinal()
.domain(["", ""])
.range([" hsl(40, 98%, 35%)", "hsl(9, 64%, 35%)"])
.unknown("hsl(227, 16%, 22%)");
// transform to features
$: countries = world?.features.map(obj => {
const { geometry, properties, _ } = obj;
//const d = path(geometry);
const fill = fillScale(properties.iso3);
const stroke = strokeScale(properties.iso3);
const newProperties = Object.assign({ ...properties }, { fill, stroke });
return Object.assign({}, { geometry, properties: newProperties });
});
// $: console.log('features', features);
//$: console.log('first', ROTATION);
</script>
<svelte:window bind:innerWidth={width} bind:innerHeight={height} />
<svg {width} {height}>
<Draggable bind:mouseX={x} bind:mouseY={y}>
{#if countries}
<path class="sphere" d={path({ type: 'Sphere' })} />
<g class="countries">
{#each countries as country}
<path
d={path(country.geometry)}
fill={country.properties.fill}
stroke={country.properties.stroke}
/>
{/each}
</g>
{/if}
</Draggable>
</svg>
<!-- markup (zero or more items) goes here -->
<style>
svg {
border: 1px solid tomato;
}
.sphere {
fill: var(--base-color-2);
}
</style>
I have the next problem I'm trying to create a draggable world globe with d3 in a svelte app, the problem that i have is when a try to drag the globe the drag action is laggy I think that my problem have someting to do with a memory leak in the draggable component I don't know if this is the main reason of this laggy behaviour. The globe was drew with svg's
This is the App link:
https://codesandbox.io/s/cocky-benz-2mk5bs
Draggable component
<script>
import { onMount, onDestroy, afterUpdate } from 'svelte';
import { mouseAdjusted } from '../lib/Utilities';
onMount(() => console.log('mounted'));
afterUpdate(() => {
//console.log('Destroyed');
});
export let mouseX;
export let mouseY;
let offset;
let isMove = false;
const start = (e) => {
isMove = true;
const element = e.target;
const target = e.target.parentElement.parentElement.getScreenCTM();
// get the mouse position in the svg shape
offset = mouseAdjusted(e.clientX, e.clientY, target);
// rest the shape mouse posicion from the shape x y coordinates
offset[1] -= +element.getAttributeNS(null, 'y');
offset[0] -= +element.getAttributeNS(null, 'x');
};
const move = (e) => {
if (isMove) {
const target = e.target.parentElement.parentElement.getScreenCTM();
const [x, y] = mouseAdjusted(e.clientX, e.clientY, target);
mouseX = offset[0] - x;
mouseY = offset[1] - y;
}
};
const end = () => {
isMove = false;
offset = null;
};
</script>
<svelte:window
on:mousemove|preventDefault|stopPropagation={move}
on:mouseup|preventDefault|stopPropagation={end}
/>
<g class="draggable" on:mousedown|preventDefault|stopPropagation={start}>
<slot />
</g>
Graph component
<script>
import { onMount, onDestroy } from "svelte";
import * as d3 from "d3";
import * as topojson from "topojson-client";
import Draggable from "./draggable.svelte";
let width = 500;
$: width = width * 0.95;
let height = 500;
$: height = height * 0.98;
let world;
let x;
let y;
let projection;
let path;
let ROTATION = [-45, -65, 0];
// Add topojsom
onMount(async () => {
const resp = await d3.json(
"/src/assets/world-administrative-boundaries.json"
);
world = await topojson.feature(resp, "world-administrative-boundaries");
});
$: ROTATION = [-x, y, 0];
$: projection = d3
.geoOrthographic()
.fitSize([width, height], world)
.scale([width / 3])
.rotate(ROTATION);
$: path = d3.geoPath(projection);
const fillScale = d3
.scaleOrdinal()
.domain(["", ""])
.range([" hsl(40, 98%, 47%)", "hsl(9, 64%, 50%)"])
.unknown("hsl(227, 16%, 42%)");
const strokeScale = d3
.scaleOrdinal()
.domain(["", ""])
.range([" hsl(40, 98%, 35%)", "hsl(9, 64%, 35%)"])
.unknown("hsl(227, 16%, 22%)");
// transform to features
$: countries = world?.features.map(obj => {
const { geometry, properties, _ } = obj;
//const d = path(geometry);
const fill = fillScale(properties.iso3);
const stroke = strokeScale(properties.iso3);
const newProperties = Object.assign({ ...properties }, { fill, stroke });
return Object.assign({}, { geometry, properties: newProperties });
});
// $: console.log('features', features);
//$: console.log('first', ROTATION);
</script>
<svelte:window bind:innerWidth={width} bind:innerHeight={height} />
<svg {width} {height}>
<Draggable bind:mouseX={x} bind:mouseY={y}>
{#if countries}
<path class="sphere" d={path({ type: 'Sphere' })} />
<g class="countries">
{#each countries as country}
<path
d={path(country.geometry)}
fill={country.properties.fill}
stroke={country.properties.stroke}
/>
{/each}
</g>
{/if}
</Draggable>
</svg>
<!-- markup (zero or more items) goes here -->
<style>
svg {
border: 1px solid tomato;
}
.sphere {
fill: var(--base-color-2);
}
</style>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论