Skip to content

Commit

Permalink
feat: add onframe param on camera animation (#1560)
Browse files Browse the repository at this point in the history
* feat: add onframe param on goToLandmark

* chore: commit changeset
  • Loading branch information
xiaoiver authored Oct 26, 2023
1 parent 1d44607 commit d2ed3d6
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .changeset/shaggy-knives-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@antv/g-plugin-device-renderer': patch
'@antv/g-camera-api': patch
---

Add onframe param in gotoLandmark.
238 changes: 238 additions & 0 deletions demo/perf-nodes-edges.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,shrink-to-fit=no"
/>
<title>Nodes & Edges</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

html,
body {
height: 100%;
}

#container {
width: 100%;
height: 100%;
}
</style>
</head>

<body>
<div id="container"></div>
<script
src="../packages/g/dist/index.umd.min.js"
type="application/javascript"
></script>
<script
src="../packages/g-webgl/dist/index.umd.min.js"
type="application/javascript"
></script>
<script
src="../packages/g-plugin-dragndrop/dist/index.umd.min.js"
type="application/javascript"
></script>
<script>
const { Circle, Line, Canvas, Text, CanvasEvent, runtime } = window.G;

const NODE_NUM = 200000;
const EDGE_NUM = 200000;

// disable CSS Parsing
runtime.enableCSSParsing = false;

// create a renderer
const webglRenderer = new window.G.WebGL.Renderer();
webglRenderer.registerPlugin(
new window.G.Dragndrop.Plugin({
isDocumentDraggable: true,
isDocumentDroppable: true,
dragstartDistanceThreshold: 10,
dragstartTimeThreshold: 100,
}),
);

// create a canvas
const canvas = new Canvas({
container: 'container',
width: 600,
height: 500,
renderer: webglRenderer,
});
const camera = canvas.getCamera();

canvas.addEventListener(CanvasEvent.READY, () => {
let nodes = [];
let texts = [];
let colors = [
'#965E04',
'#C89435',
'#F7A456',
'#AFCF8A',
'#7B39DE',
'#B095C0',
'#D24556',
'#93C2FA',
'#9DB09E',
'#F8C821',
];
let num = Math.floor(Math.sqrt(NODE_NUM) + 0.5);

const sourceMap = new WeakMap();
const targetMap = new WeakMap();
for (let i = 0; i < NODE_NUM; i++) {
const fill = colors[Math.floor(Math.random() * colors.length) || 0];
const circle = new Circle({
style: {
cx: (i % num) * 10,
cy: Math.floor(i / num) * 10,
fill,
r: 4,
// draggable: true
},
});
nodes.push(circle);
sourceMap.set(circle, []);
targetMap.set(circle, []);

circle.addEventListener('mouseenter', () => {
circle.style.fill = 'red';
console.log('circle', i);
});
circle.addEventListener('mouseleave', () => {
circle.style.fill = fill;
});

// if (i === NODE_NUM - 1) {
// const text = new Text({
// style: {
// x: (i % num) * 10,
// y: Math.floor(i / num) * 10,
// fontSize: 10,
// fill: 'black',
// text: `${i}`,
// },
// });
// texts.push(text);
// }
}

for (let i = 0; i < EDGE_NUM; i++) {
const source = nodes[Math.floor(Math.random() * NODE_NUM)];
const target = nodes[Math.floor(Math.random() * NODE_NUM)];
const line = new Line({
style: {
x1: source.style.cx,
y1: source.style.cy,
x2: target.style.cx,
y2: target.style.cy,
lineWidth: 0.3,
stroke: 'grey',
},
});

const sourceEdges = sourceMap.get(source);
sourceEdges.push(line);
const targetEdges = targetMap.get(target);
targetEdges.push(line);

canvas.appendChild(line);

// line.addEventListener("mouseenter", () => {
// line.style.stroke = "red";
// });
// line.addEventListener("mouseleave", () => {
// line.style.stroke = "grey";
// });
}

nodes.forEach((node) => {
canvas.appendChild(node);
});
texts.forEach((text) => {
canvas.appendChild(text);
});

let shiftX = 0;
let shiftY = 0;
function moveAt(target, canvasX, canvasY) {
const x = canvasX - shiftX;
const y = canvasY - shiftY;
target.setPosition(x, y);
const sourceEdges = sourceMap.get(target);
const targetEdges = targetMap.get(target);
sourceEdges.forEach((edge) => {
edge.attr({
x1: x,
y1: y,
});
});
targetEdges.forEach((edge) => {
edge.attr({
x2: x,
y2: y,
});
});
}

canvas.addEventListener('dragstart', function (e) {
// if (e.target === canvas.document) {
// } else {
// const [x, y] = e.target.getPosition();
// shiftX = e.canvasX - x;
// shiftY = e.canvasY - y;
// moveAt(e.target, e.canvasX, e.canvasY);
// }
});
canvas.addEventListener('drag', function (e) {
// if (e.target === canvas.document) {
camera.pan(-e.dx * 10, -e.dy * 10);
// } else {
// moveAt(e.target, e.canvasX, e.canvasY);
// }
});

// handle mouse wheel event
const bindWheelHandler = () => {
// update Camera's zoom
// @see https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js
const minZoom = 0;
const maxZoom = Infinity;
canvas
.getContextService()
.getDomElement() // g-canvas/webgl 为 <canvas>,g-svg 为 <svg>
.addEventListener(
'wheel',
(e) => {
// canvas.getConfig().disableHitTesting = true;
e.preventDefault();
let zoom;
if (e.deltaY < 0) {
zoom = Math.max(
minZoom,
Math.min(maxZoom, camera.getZoom() / 0.95),
);
} else {
zoom = Math.max(
minZoom,
Math.min(maxZoom, camera.getZoom() * 0.95),
);
}
camera.setZoom(zoom);
},
{ passive: false },
);
};
bindWheelHandler();
});
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions packages/g-camera-api/src/AdvancedCamera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export class AdvancedCamera extends Camera {
easing: string;
easingFunction: TypeEasingFunction;
duration: number;
onframe: (t: number) => void;
onfinish: () => void;
}> = {},
) {
Expand All @@ -210,6 +211,7 @@ export class AdvancedCamera extends Camera {
duration = 100,
easingFunction = undefined,
onfinish = undefined,
onframe = undefined,
} = isNumber(options) ? { duration: options } : options;
const epsilon = 0.01;

Expand Down Expand Up @@ -284,6 +286,9 @@ export class AdvancedCamera extends Camera {
this.triggerUpdate();

if (elapsed < duration) {
if (onframe) {
onframe(t);
}
this.landmarkAnimationID = this.canvas.requestAnimationFrame(animate);
}
};
Expand Down
4 changes: 4 additions & 0 deletions packages/g-plugin-device-renderer/src/drawcalls/Instanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,10 @@ export abstract class Instanced {
name: string,
value: any,
) {
if (objects.length === 0) {
return;
}

const stylePacked = [
'opacity',
'fillOpacity',
Expand Down
2 changes: 1 addition & 1 deletion packages/g-plugin-device-renderer/src/renderer/Batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { RenderInst } from '../render/RenderInst';
/**
* render order start from 0, our default camera's Z is 500
*/
export const RENDER_ORDER_SCALE = 1 / 200;
export const RENDER_ORDER_SCALE = 500 / 1000000;

/**
* A container for multiple display objects with the same `style`,
Expand Down

0 comments on commit d2ed3d6

Please sign in to comment.