- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
614 lines
29 KiB
HTML
Executable File
614 lines
29 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Treeload animation GoJS Sample</title>
|
|
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
|
<meta name="description" content="Loading a tree with custom GoJS animation." />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
<script src="../release/go.js"></script>
|
|
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
|
|
<script id="code">
|
|
function init() {
|
|
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
|
|
|
|
var $ = go.GraphObject.make;
|
|
var animationDiagram = null;
|
|
// Sliders for customizing the links and duration of the animation
|
|
var durationSlider = document.getElementById("duration");
|
|
var durationOutput = document.getElementById("durationDisplay");
|
|
durationOutput.innerHTML = durationSlider.value;
|
|
durationSlider.oninput = function () {
|
|
durationOutput.innerHTML = this.value;
|
|
}
|
|
var cornerSlider = document.getElementById("corner");
|
|
var cornerOutput = document.getElementById("cornerDisplay");
|
|
cornerOutput.innerHTML = cornerSlider.value;
|
|
cornerSlider.oninput = function () {
|
|
cornerOutput.innerHTML = this.value;
|
|
}
|
|
var curvatureSlider = document.getElementById("curvature");
|
|
var curvatureOutput = document.getElementById("curvatureDisplay");
|
|
curvatureOutput.innerHTML = curvatureSlider.value;
|
|
curvatureSlider.oninput = function () {
|
|
curvatureOutput.innerHTML = this.value;
|
|
}
|
|
|
|
myDiagram =
|
|
$(go.Diagram, "myDiagramDiv",
|
|
{
|
|
// We want no default animation when the diagram loads
|
|
"animationManager.isInitial": false,
|
|
autoScale: go.Diagram.Uniform,
|
|
// Disable the diagram during the animation so that the links cannot be moved, which would call compute points
|
|
// The Diagram is reset to enabled when the animation is finished
|
|
isEnabled: false,
|
|
layout: $(go.ForceDirectedLayout,
|
|
{
|
|
defaultSpringLength: 20, // forces nodes closer together (default: 50)
|
|
defaultSpringStiffness: 0.20, // forces nodes closer together (default: 0.05)
|
|
isOngoing: false,
|
|
isRealtime: false
|
|
})
|
|
});
|
|
|
|
myDiagram.nodeTemplate =
|
|
$(go.Node, "Auto",
|
|
{
|
|
locationSpot: go.Spot.Center,
|
|
resizable: true,
|
|
rotatable: true,
|
|
opacity: 0
|
|
},
|
|
new go.Binding("location"),
|
|
new go.Binding("desiredSize"),
|
|
$(go.Shape, "RoundedRectangle", { fill: "lightBlue" }),
|
|
$(go.TextBlock, new go.Binding("text", "key"))
|
|
);
|
|
|
|
myDiagram.linkTemplate =
|
|
$(go.Link,
|
|
{ opacity: 0 },
|
|
$(go.Shape),
|
|
$(go.Shape, { toArrow: "Standard" })
|
|
);
|
|
|
|
// Generate a tree
|
|
var treeArr = [{ key: 0 }];
|
|
var childCount = 0;
|
|
var currParent = 0;
|
|
for (var i = 1; i < 100; i++) {
|
|
var newNode = {
|
|
key: i,
|
|
parent: treeArr[currParent].key
|
|
}
|
|
treeArr.push(newNode);
|
|
childCount++;
|
|
// How many Children the node will have
|
|
if (childCount > 3) {
|
|
childCount = 0;
|
|
currParent++;
|
|
}
|
|
}
|
|
myDiagram.model = new go.TreeModel(treeArr);
|
|
|
|
var queue = [myDiagram.nodes.first()];
|
|
// Start with the root node visible
|
|
myDiagram.commit(function() {
|
|
myDiagram.nodes.first().opacity = 1;
|
|
}, null);
|
|
|
|
// Begin
|
|
animateLinks(queue);
|
|
|
|
// Given an array of nodes, recursively animate their outgoing links and connected nodes, layer by layer.
|
|
// All the nodes in a layer will be stored and therefore animated before the function moves onto the next layer
|
|
function animateLinks(q) {
|
|
var newQueue = [];
|
|
var originalValues = new go.List();
|
|
// One animation per layer, which will contain all links in the layer
|
|
var animation = new go.Animation();
|
|
animation.duration = Number(durationSlider.value);
|
|
animation.easing = go.Animation.EaseLinear;
|
|
// Each time the function is called, the queue represents the entire layer, iterate through it removing each one
|
|
while (q.length > 0) {
|
|
var tempNode = q.shift();
|
|
// Add animation for all links that stem from the given node
|
|
tempNode.linksConnected.each(function (link) {
|
|
if (link.fromNode === tempNode) {
|
|
myDiagram.startTransaction("animate link");
|
|
originalValues.push({
|
|
link: link,
|
|
makeGeometry: link.makeGeometry,
|
|
oldPoints: link.points,
|
|
geometry: link.elt(0).geometry.copy()
|
|
});
|
|
// If there is an arrow, record the initial segment index and orientation to reset at the end, then animate the scale with the link
|
|
if (link.elements.count > 1) {
|
|
originalValues.last().oldSegIndex = [];
|
|
originalValues.last().oldSegOrientation = link.elt(1).segmentOrientation;
|
|
for (var i = 1; i < link.elements.count; i++) {
|
|
// Calculate waiting time for the element depending on how far it is along the link
|
|
if (link.geometry.figures.length === 0 || link.elt(i).segmentFraction < 0) {
|
|
offsetTime = link.elt(i).segmentFraction * animation.duration;
|
|
} else {
|
|
offsetTime = link.elt(i).segmentIndex / link.points.count * animation.duration
|
|
}
|
|
// Start scale animations after an offset
|
|
animation.add(link.elt(i), "customScale", 0.01, { endValue: link.elt(1).scale, offsetTime: offsetTime });
|
|
originalValues.last().oldSegIndex.push(link.elt(i).segmentIndex);
|
|
}
|
|
}
|
|
animation.add(link, "opacity", 0.01, 1)
|
|
// Node should fade in while the link is moving
|
|
animation.add(link.toNode, "opacity", 0, 1);
|
|
// linear links have no geometry, and are treated differently
|
|
if (link.geometry.figures.length === 0) {
|
|
animation.add(link, "linearLinkAnim", link.geometry, myDiagram.layout)
|
|
} else {
|
|
animation.add(link, "segmentLinkAnim", link.geometry, myDiagram.layout)
|
|
}
|
|
// New queue to store the next layer
|
|
newQueue.push(link.toNode);
|
|
myDiagram.commitTransaction("animate link")
|
|
}
|
|
});
|
|
}
|
|
q = newQueue;
|
|
// Exit if the next layer is empty, meaning there are no more links to animate
|
|
if (q.length === 0) {
|
|
myDiagram.isEnabled = true;
|
|
return;
|
|
}
|
|
|
|
// Chain animatons for each layer
|
|
animation.finished = function () {
|
|
myDiagram.startTransaction("change link");
|
|
originalValues.each(function (newVal) {
|
|
var link = newVal.link;
|
|
if (link.elements.count > 1) {
|
|
// Set original values of each part of the link back to what they were
|
|
link.elt(1).segmentOrientation = newVal.oldSegOrientation;
|
|
for (var i = 1; i < link.elements.count; i++) {
|
|
link.elt(i).segmentIndex = newVal.oldSegIndex[i - 1];
|
|
}
|
|
}
|
|
// Set the changed properties of the link back to what they were before the animation.
|
|
link.elt(0).geometry = newVal.geometry;
|
|
link.makeGeometry = newVal.makeGeometry;
|
|
// Setting the points back to what they were will call the default makeGeometry
|
|
link.points = newVal.oldPoints;
|
|
});
|
|
animateLinks(q);
|
|
myDiagram.commitTransaction("change link");
|
|
}
|
|
animation.start();
|
|
}
|
|
|
|
// Functions called by buttons that reset the layout and reanimate the links
|
|
document.getElementById('orth').addEventListener('click', orthog);
|
|
|
|
function orthog() {
|
|
myDiagram.startTransaction("change links");
|
|
myDiagram.linkTemplate =
|
|
$(go.Link,
|
|
{
|
|
opacity: 0, // links start out invisible
|
|
routing: go.Link.Orthogonal,
|
|
corner: Number(cornerSlider.value)
|
|
},
|
|
$(go.Shape),
|
|
$(go.Shape, { toArrow: "Standard" })
|
|
);
|
|
myDiagram.layout.doLayout(myDiagram);
|
|
// Root node should start visible
|
|
myDiagram.nodes.first().opacity = 1;
|
|
myDiagram.commitTransaction("change links");
|
|
// Begin to recursively animate links
|
|
animateLinks([myDiagram.nodes.first()]);
|
|
}
|
|
|
|
document.getElementById('bez').addEventListener('click', bezierLinks);
|
|
|
|
function bezierLinks() {
|
|
myDiagram.startTransaction("change links");
|
|
myDiagram.linkTemplate =
|
|
$(go.Link,
|
|
{
|
|
opacity: 0, // links start out invisible
|
|
curve: go.Link.Bezier,
|
|
curviness: Number(curvatureSlider.value)
|
|
},
|
|
$(go.Shape),
|
|
$(go.Shape, { toArrow: "Standard" })
|
|
);
|
|
myDiagram.layout.doLayout(myDiagram);
|
|
// Root node should start visible
|
|
myDiagram.nodes.first().opacity = 1;
|
|
myDiagram.commitTransaction("change links");
|
|
// Begin to recursively animate links
|
|
animateLinks([myDiagram.nodes.first()]);
|
|
}
|
|
|
|
document.getElementById('linear').addEventListener('click', linearLinks);
|
|
|
|
function linearLinks() {
|
|
myDiagram.startTransaction("change links");
|
|
myDiagram.linkTemplate =
|
|
$(go.Link,
|
|
{ opacity: 0 }, // links start out invisible
|
|
$(go.Shape),
|
|
$(go.Shape, { toArrow: "Standard" })
|
|
);
|
|
myDiagram.layout.doLayout(myDiagram);
|
|
// Root node should start visible
|
|
myDiagram.nodes.first().opacity = 1;
|
|
myDiagram.commitTransaction("change links");
|
|
// Begin to recursively animate links
|
|
animateLinks([myDiagram.nodes.first()]);
|
|
}
|
|
}
|
|
|
|
// Animation for changing the scale after a delay, endObj must contain the end scale but also the delay (offsetTime)
|
|
go.AnimationManager.defineAnimationEffect('customScale', function (part, startValue, endObj, easing, currentTime, duration, animation) {
|
|
if (endObj.offsetTime < currentTime) {
|
|
part.scale = easing(currentTime - endObj.offsetTime, startValue, (endObj.endValue - startValue), duration - endObj.offsetTime);
|
|
} else {
|
|
part.scale = startValue;
|
|
}
|
|
})
|
|
|
|
// General animation for links that are made up of path segments, linear links do not have this, so therefore must use a special case
|
|
go.AnimationManager.defineAnimationEffect('segmentLinkAnim',
|
|
function (link, geometry, layout, easing, currentTime, duration, animation) {
|
|
var animationState = animation.getTemporaryState(link);
|
|
animationState.currentTime = currentTime;
|
|
if (animationState.initial === undefined) {
|
|
// Only do these things once
|
|
animationState.points = [];
|
|
// The shapes geometry requres an offset from the links bounds so that it will line up properly
|
|
animationState.offsetX = link.elt(0).actualBounds.x;
|
|
animationState.offsetY = link.elt(0).actualBounds.y;
|
|
|
|
// Points that when added to the list of points will be used to create the bounds of the link, therefore they are the corner points of the original bounds
|
|
var boundX = link.actualBounds.x;
|
|
var boundY = link.actualBounds.y;
|
|
animationState.boundPoint1 = new go.Point(boundX, boundY);
|
|
animationState.boundPoint2 = new go.Point(boundX + link.actualBounds.width, boundY + link.actualBounds.height);
|
|
|
|
//Points used to hold the initial points of a quadratic bezier
|
|
animationState.point1 = null;
|
|
animationState.startValue = new go.Point(geometry.figures.first().startX, geometry.figures.first().startY);
|
|
animationState.endValue = null;
|
|
|
|
//Point from the link which will be used to create the new points that the arrow will follow along on
|
|
animationState.initPoint = link.points.elt(0).copy();
|
|
// Assuming the second shape is the arrow which will follow
|
|
if (link.elements.count > 1) {
|
|
// Change the segment index so that it will follow the segment which is being created
|
|
link.elt(1).segmentIndex = 2;
|
|
// Set this to none so that the angle can be manually set
|
|
link.elt(1).segmentOrientation = go.Link.None;
|
|
}
|
|
animationState.origPoints = link.points.copy();
|
|
// Shift all other objects segment indexes over so that they maintain their positions as the first four points are being used to animate the arrow
|
|
for (var i = 2; i < link.elements.count; i++) {
|
|
if (link.elt(i).segmentIndex < link.points.count) {
|
|
link.elt(i).segmentIndex += 4;
|
|
}
|
|
}
|
|
|
|
animationState.currX = 0;
|
|
animationState.currY = 0;
|
|
animationState.delX = 0;
|
|
animationState.delY = 0;
|
|
|
|
// Add these to the animationState so they can be used in the custom make geometry
|
|
animationState.totalDuration = duration;
|
|
animationState.easing = easing;
|
|
|
|
//Set the links makeGeometry to the custom one, passing in the objects that it will use each time it is called
|
|
link.makeGeometry = segmentMakeGeometry(animationState, geometry.copy(), link);
|
|
|
|
// Calculate the duration for all beziers since they all are the same length in the given link
|
|
var totalSegmentLength = 0;
|
|
var prevValueX = animationState.startValue.x;
|
|
var prevValueY = animationState.startValue.y;
|
|
var bezSegments = 0;
|
|
// find the total length of all the linear segments
|
|
geometry.figures.first().segments.each(function (sgmt) {
|
|
if (sgmt.type === go.PathSegment.QuadraticBezier) {
|
|
bezSegments++;
|
|
} else {
|
|
var length = Math.max(Math.abs(prevValueX - sgmt.endX), Math.abs(prevValueY - sgmt.endY));
|
|
totalSegmentLength += length;
|
|
}
|
|
prevValueX = sgmt.endX;
|
|
prevValueY = sgmt.endY;
|
|
})
|
|
// The duration for the Bezier corners on an orthogonal link is calculated by taking a fraction of the total duration based on how long the bezier corners are,
|
|
// Then that is divided by how many corners there are to get the average time needed for each segment
|
|
animationState.bezierDuration = duration * Math.abs(geometry.flattenedTotalLength - Math.abs(
|
|
totalSegmentLength)) /
|
|
(bezSegments * geometry.flattenedTotalLength);
|
|
|
|
animationState.changedSegments = new go.List();
|
|
animationState.firstItr = true;
|
|
animationState.currSegment = 0;
|
|
animationState.elaDuration = 0;
|
|
animationState.duration = 0;
|
|
animationState.initial = true;
|
|
}
|
|
|
|
animationState.hasTicked = false;
|
|
|
|
/*
|
|
Create a new set of points for the bounds, arrows, and labels.
|
|
There are a total of eight points which are used to make two bezier curves. The first one to generate the bounds of the link along
|
|
with the position of the arrowhead, and the second one to be used to hold the position of all the labels. The link uses the start and end points of
|
|
each four point bezier to calculate its bounds along with the geometries, so the start and end of the first one are the corners of the actual bounds
|
|
of the link at the beginning of the animation.
|
|
*/
|
|
var tempPoints = new go.List();
|
|
// Add points for the first bezier, bound point 1 and 2 are used to create the actual bounds of the link
|
|
tempPoints.push(animationState.boundPoint1);
|
|
var newPoint = new go.Point(animationState.initPoint.x + animationState.currX,
|
|
animationState.initPoint.y + animationState.currY);
|
|
tempPoints.push(newPoint);
|
|
tempPoints.push(newPoint);
|
|
tempPoints.push(animationState.boundPoint2);
|
|
|
|
// Add points from the original bezier which will be used to hold the position of the objects
|
|
animationState.origPoints.each(function (point) {
|
|
tempPoints.push(point);
|
|
});
|
|
// Changing the points will cause GoJS to call the modified makeGeometry which will remake the geometry
|
|
link.points = tempPoints;
|
|
if (link.elements.count > 1) {
|
|
// Set angle of the arrow using the most recent points
|
|
var newAngle = Math.atan2(animationState.delY, animationState.delX);
|
|
link.elt(1).angle = newAngle * 180 / Math.PI;
|
|
}
|
|
}
|
|
);
|
|
|
|
go.AnimationManager.defineAnimationEffect('linearLinkAnim',
|
|
function (link, geometry, endValue, easing, currentTime, duration, animation) {
|
|
var animationState = animation.getTemporaryState(link);
|
|
animationState.currentTime = currentTime
|
|
if (animationState.initial === undefined) {
|
|
// Put properties on the animationState so it can be referenced by the modified makeGeometry function
|
|
animationState.duration = duration;
|
|
animationState.easing = easing;
|
|
animationState.initial = true;
|
|
link.makeGeometry = linearMakeGeometry(animationState, geometry.copy(), link);
|
|
// Changing the points will cause GoJS to call the modified makeGeometry
|
|
link.points = link.points.copy();
|
|
}
|
|
if (link.elements.count !== 1) {
|
|
link.elt(1).segmentFraction = 1 - easing(currentTime, 0, 1, duration)
|
|
}
|
|
}
|
|
);
|
|
|
|
// Function returns points to draw a cubic bezier
|
|
function sliceCubicBezier(currentTime, p1, p2, p3, p4, segment, duration, offsetX, offsetY) {
|
|
var t = currentTime / duration;
|
|
var u = 1 - t;
|
|
/*
|
|
This function takes the original points of the link's bezier curve and returns four different points that will draw a segment of the curve
|
|
The algorithm consists of four equations which use the start t to the end t, where t represents the point of the curve going from 0 to 1 which
|
|
in this case is related to the time, however the t0 is always 0 which simplifies the equations. The first point should always stay the same
|
|
because the segment of the curve drawn will always start at the fromNode
|
|
*/
|
|
newp2 = addPoints(scalarMult(p1, u), scalarMult(p2, t));
|
|
newp3 = scalarMult(p1, u * u).add(scalarMult(p2, 2 * t * u)).add(scalarMult(p3, t * t));
|
|
newp4 = scalarMult(p1, u * u * u).add(scalarMult(p2, 3 * t * u * u)).add(scalarMult(p3, 3 * t * t * u)).add(
|
|
scalarMult(p4, t * t * t));
|
|
segment.point1X = newp2.x + offsetX;
|
|
segment.point1Y = newp2.y + offsetY;
|
|
segment.point2X = newp3.x + offsetX;
|
|
segment.point2Y = newp3.y + offsetY;
|
|
segment.endX = newp4.x + offsetX;
|
|
segment.endY = newp4.y + offsetY;
|
|
}
|
|
|
|
// Uses same algorithm just for a quadratic bezier
|
|
function sliceQuadBezier(currentTime, p1, p2, p3, segment, duration, offsetX, offsetY) {
|
|
var t = currentTime / duration;
|
|
var u = 1 - t;
|
|
// Same concept as the cubic algorithm minus a point
|
|
newp2 = addPoints(scalarMult(p1, u), scalarMult(p2, t));
|
|
newp3 = scalarMult(p1, u * u).add(scalarMult(p2, 2 * t * u)).add(scalarMult(p3, t * t));
|
|
segment.point1X = newp2.x + offsetX;
|
|
segment.point1Y = newp2.y + offsetY;
|
|
segment.endX = newp3.x + offsetX;
|
|
segment.endY = newp3.y + + offsetY;
|
|
}
|
|
|
|
function scalarMult(point, factor) {
|
|
return new go.Point(point.x * factor, point.y * factor);
|
|
}
|
|
|
|
function addPoints(a, b) {
|
|
return new go.Point().add(a).add(b);
|
|
}
|
|
|
|
// Geometry for basic linear case
|
|
function linearMakeGeometry(animationState, geometry, link) {
|
|
var startValue = new go.Point(geometry.startX, geometry.startY);
|
|
var endValue = new go.Point(geometry.endX, geometry.endY);
|
|
|
|
function tempMakeGeometry() {
|
|
var currX = animationState.easing(animationState.currentTime, startValue.x, (endValue.x - startValue.x),
|
|
animationState.duration);
|
|
var currY = animationState.easing(animationState.currentTime, startValue.y, (endValue.y - startValue.y),
|
|
animationState.duration);
|
|
var tempGeo = link.elt(0).geometry.copy();
|
|
tempGeo.endX = currX;
|
|
tempGeo.endY = currY;
|
|
return tempGeo;
|
|
}
|
|
return tempMakeGeometry;
|
|
}
|
|
|
|
/*
|
|
This custom makeGeometry slowly builds the geometry of the link, animating a segment then adding it to the geometry until all of the segments
|
|
have been iterated through. Orthogonal links are made up of linear path segments and quadratic bezier corners which have to be treated
|
|
differently. The current point that the animation is on is then returned so the arrowhead can be drawn.
|
|
*/
|
|
function segmentMakeGeometry(animationState, geometry, link) {
|
|
var startValX = geometry.figures.first().startX + animationState.offsetX;
|
|
var startValY = geometry.figures.first().startY + animationState.offsetY;
|
|
var prevptX = 0;
|
|
var prevptY = 0;
|
|
var currptX = 0;
|
|
var currptY = 0;
|
|
|
|
function tempMakeGeometry() {
|
|
animationState.newGeometry = geometry.copy();
|
|
|
|
// Offset the position values so it is in the right spot relative to the document coordinates
|
|
animationState.newGeometry.figures.first().startX += animationState.offsetX;
|
|
animationState.newGeometry.figures.first().startY += animationState.offsetY;
|
|
if (animationState.currSegment > geometry.figures.first().segments.length - 1) {
|
|
return animationState.newGeometry;
|
|
}
|
|
var shouldPop = true;
|
|
var scaledTime = animationState.currentTime - animationState.elaDuration;
|
|
/*
|
|
Because multiple segments are being modified in order in this animation and each one has a separate duration, the time used in the
|
|
easing functions must be at or below the duration. Usually the animation would stop if the current time exceeded the duration but
|
|
because it is continuing to animate other segments after, the time has to be brought within the duration of the current segment being modified
|
|
*/
|
|
var usedTime = scaledTime;
|
|
if (scaledTime > animationState.duration) {
|
|
usedTime = animationState.duration;
|
|
}
|
|
// Segment can only be modified once before it becomes frozen, which means that a copy must be made and modified
|
|
var currSegment = geometry.figures.first().segments.elt(animationState.currSegment).copy();
|
|
// Corner / Quadratic Bezier case
|
|
if (currSegment.type === go.PathSegment.QuadraticBezier) {
|
|
// Only do once per segment
|
|
if (animationState.firstItr === true) {
|
|
// Set the initial points of the curve which are used to calculate the peice of the bezier at a given time within the duration
|
|
animationState.point1 = new go.Point(currSegment.point1X, currSegment.point1Y);
|
|
animationState.endValue = new go.Point(currSegment.endX, currSegment.endY);
|
|
animationState.duration = animationState.bezierDuration;
|
|
animationState.firstItr = false;
|
|
// Check to see if the scaled time is less than the duration on the first iteration
|
|
if (scaledTime > animationState.duration) {
|
|
usedTime = animationState.duration;
|
|
}
|
|
}
|
|
sliceQuadBezier(usedTime, animationState.startValue, animationState.point1, animationState.endValue,
|
|
currSegment, animationState.duration, animationState.offsetX, animationState.offsetY);
|
|
} else if (currSegment.type === go.PathSegment.Bezier) {
|
|
if (animationState.firstItr === true) {
|
|
animationState.points = [];
|
|
|
|
animationState.points.push(
|
|
new go.Point(geometry.figures.first().startX, geometry.figures.first().startY));
|
|
animationState.points.push(new go.Point(geometry.figures.first().segments.first().point1X, geometry.figures.first().segments.first().point1Y));
|
|
animationState.points.push(new go.Point(geometry.figures.first().segments.first().point2X, geometry.figures.first().segments.first().point2Y));
|
|
animationState.points.push(new go.Point(geometry.figures.first().segments.first().endX, geometry.figures.first().segments.first().endY));
|
|
animationState.duration = animationState.totalDuration;
|
|
animationState.firstItr = false;
|
|
if (scaledTime > animationState.duration) {
|
|
usedTime = animationState.duration;
|
|
}
|
|
}
|
|
var tempGeo = geometry.copy();
|
|
|
|
// Function which modifies the segment to make a portion of the bezier curve depending on the time relative to the duration
|
|
sliceCubicBezier(usedTime, animationState.points[0], animationState.points[1],
|
|
animationState.points[2],
|
|
animationState.points[3],
|
|
currSegment, animationState.duration, animationState.offsetX,
|
|
animationState.offsetY);
|
|
} else { // Line segment case
|
|
// Only do once per segment
|
|
if (animationState.firstItr === true) {
|
|
animationState.endValue = new go.Point(currSegment.endX, currSegment.endY);
|
|
// Calculate duration based on the total duration and the size of this segment compared to the entire link
|
|
animationState.duration =
|
|
animationState.totalDuration * Math.max(Math.abs(animationState.startValue.x - animationState.endValue.x),
|
|
Math.abs(animationState.startValue.y - animationState.endValue.y)) / geometry.flattenedTotalLength;
|
|
animationState.firstItr = false;
|
|
// Check to see if the scaled time is less than the duration on the first iteration
|
|
if (scaledTime > animationState.duration) {
|
|
usedTime = animationState.duration;
|
|
}
|
|
}
|
|
// Lines uses the given easing function to get their end values
|
|
var currX = animationState.easing(usedTime, animationState.startValue.x, animationState.endValue.x -
|
|
animationState.startValue.x, animationState.duration);
|
|
var currY = animationState.easing(usedTime, animationState.startValue.y, animationState.endValue.y -
|
|
animationState.startValue.y, animationState.duration);
|
|
if (animationState.duration === 0) {
|
|
currX = animationState.endValue.x;
|
|
currY = animationState.endValue.y;
|
|
}
|
|
currSegment.endX = currX + animationState.offsetX;
|
|
currSegment.endY = currY + animationState.offsetY;
|
|
}
|
|
animationState.changedSegments.push(currSegment);
|
|
// List will freeze after being changed once so a copy is made and used every tick
|
|
animationState.newGeometry.figures.first().segments = animationState.changedSegments.copy();
|
|
if (scaledTime > animationState.duration) {
|
|
var tempList = new go.List();
|
|
animationState.startValue = animationState.endValue;
|
|
animationState.elaDuration += scaledTime;
|
|
// Reset first Iteration so that the correct points will be set and used throughout that given part of the animation
|
|
animationState.firstItr = true;
|
|
animationState.currSegment++;
|
|
currptX = currSegment.endX - startValX;
|
|
currptY = currSegment.endY - startValY;
|
|
// Do not remove the segment the last time in order to build up the geometry
|
|
shouldPop = false;
|
|
}
|
|
currptX = currSegment.endX - startValX;
|
|
currptY = currSegment.endY - startValY;
|
|
animationState.currX = currptX;
|
|
animationState.currY = currptY;
|
|
// Only set the delta X and Ys every tick as the makeGeometry is called multiple times within a tick
|
|
if (!animationState.hasTicked) {
|
|
animationState.delX = currptX - prevptX;
|
|
animationState.delY = currptY - prevptY;
|
|
animationState.hasTicked = true;
|
|
}
|
|
prevptY = currptY;
|
|
prevptX = currptX;
|
|
|
|
// Remove last segment from the changedSegments list because it will be added the next time makeGeometry is called
|
|
if (shouldPop) {
|
|
animationState.changedSegments.pop();
|
|
}
|
|
return animationState.newGeometry;
|
|
}
|
|
return tempMakeGeometry;
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<body onload="init()">
|
|
<div id="sample">
|
|
<!-- The DIV for the Diagram needs an explicit size or else we won't see anything.
|
|
This also adds a border to help see the edges of the viewport. -->
|
|
<div id="myDiagramDiv" style="border: solid 1px black; width:800px; height:800px"></div>
|
|
<button id="orth">Load Orthogonal Links</button>
|
|
<button id="bez">Load Bezier Links</button>
|
|
<button id="linear">Load Linear Links</button><br> Duration: <input type="range" min="100" max="3000" value="500"
|
|
class="slider" id="duration">
|
|
<span id="durationDisplay"></span><br> Corner: <input type="range" min="0" max="100" value="0" class="slider"
|
|
id="corner">
|
|
<span id="cornerDisplay"></span><br> Curvature: <input type="range" min="-50" max="50" value="40" class="slider"
|
|
id="curvature">
|
|
<span id="curvatureDisplay"></span><br>
|
|
<p>
|
|
This sample demonstrates defining custom animation effects with <a>AnimationManager,defineAnimationEffect</a>,
|
|
and chaining animations to recursively animate a tree.
|
|
</p>
|
|
</div>
|
|
</body>
|
|
</html> |