/** * @fileOverview Default animation funciton * @author sima.zhang */ var Util = require('../util'); var G = require('../renderer'); var PathUtil = Util.PathUtil; function getClip(coord) { var start = coord.start; var end = coord.end; var width = coord.getWidth(); var height = coord.getHeight(); var margin = 200; var startAngle; var endAngle; var center; var radius; var clip; if (coord.isPolar) { radius = coord.getRadius(); center = coord.getCenter(); startAngle = coord.startAngle; endAngle = coord.endAngle; clip = new G.Fan({ attrs: { x: center.x, y: center.y, rs: 0, re: radius + margin, startAngle: startAngle, endAngle: startAngle } }); clip.endState = { endAngle: endAngle }; } else { clip = new G.Rect({ attrs: { x: start.x - margin, y: end.y - margin, width: coord.isTransposed ? width + margin * 2 : 0, height: coord.isTransposed ? 0 : height + margin * 2 } }); if (coord.isTransposed) { clip.endState = { height: height + margin * 2 }; } else { clip.endState = { width: width + margin * 2 }; } } clip.isClip = true; return clip; } // 获取图形的包围盒 function getPointsBox(points) { if (Util.isEmpty(points)) { return null; } var minX = points[0].x; var maxX = points[0].x; var minY = points[0].y; var maxY = points[0].y; Util.each(points, function (point) { minX = minX > point.x ? point.x : minX; maxX = maxX < point.x ? point.x : maxX; minY = minY > point.y ? point.y : minY; maxY = maxY < point.y ? point.y : maxY; }); return { minX: minX, maxX: maxX, minY: minY, maxY: maxY, centerX: (minX + maxX) / 2, centerY: (minY + maxY) / 2 }; } function getAngle(shape, coord) { var points = shape.points || shape.get('origin').points; var box = getPointsBox(points); var endAngle; var startAngle; var coordStartAngle = coord.startAngle; var coordEndAngle = coord.endAngle; var diffAngle = coordEndAngle - coordStartAngle; if (coord.isTransposed) { endAngle = box.maxY * diffAngle; startAngle = box.minY * diffAngle; } else { endAngle = box.maxX * diffAngle; startAngle = box.minX * diffAngle; } endAngle += coordStartAngle; startAngle += coordStartAngle; return { startAngle: startAngle, endAngle: endAngle }; } function getAnimateParam(animateCfg, index, id) { var result = {}; if (animateCfg.delay) { result.delay = Util.isFunction(animateCfg.delay) ? animateCfg.delay(index, id) : animateCfg.delay; } result.easing = Util.isFunction(animateCfg.easing) ? animateCfg.easing(index, id) : animateCfg.easing; result.duration = Util.isFunction(animateCfg.duration) ? animateCfg.duration(index, id) : animateCfg.duration; result.callback = animateCfg.callback; return result; } function scaleInY(shape, animateCfg) { var id = shape._id; var index = shape.get('index'); var box = shape.getBBox(); var points = shape.get('origin').points; var x = (box.minX + box.maxX) / 2; var y; if (points[0].y - points[1].y <= 0) { // 当顶点在零点之下 y = box.maxY; } else { y = box.minY; } var v = [x, y, 1]; shape.apply(v); shape.attr('transform', [['t', -x, -y], ['s', 1, 0.01], ['t', x, y]]); var endState = { transform: [['t', -x, -y], ['s', 1, 100], ['t', x, y]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, animateParam.callback, animateParam.delay); } function scaleInX(shape, animateCfg) { var id = shape._id; var index = shape.get('index'); var box = shape.getBBox(); var points = shape.get('origin').points; var x; var y = (box.minY + box.maxY) / 2; if (points[0].y - points[1].y > 0) { // 当顶点在零点之下 x = box.maxX; } else { x = box.minX; } var v = [x, y, 1]; shape.apply(v); shape.attr({ transform: [['t', -x, -y], ['s', 0.01, 1], ['t', x, y]] }); var endState = { transform: [['t', -x, -y], ['s', 100, 1], ['t', x, y]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, animateParam.callback, animateParam.delay); } function lineWidthOut(shape, animateCfg) { var endState = { lineWidth: 0, opacity: 0 }; var id = shape._id; var index = shape.get('index'); var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, function () { shape.remove(); }, animateParam.delay); } function zoomIn(shape, animateCfg, coord) { var id = shape._id; var index = shape.get('index'); var x; var y; if (coord.isPolar && shape.name !== 'point') { x = coord.getCenter().x; y = coord.getCenter().y; } else { var box = shape.getBBox(); x = (box.minX + box.maxX) / 2; y = (box.minY + box.maxY) / 2; } var v = [x, y, 1]; shape.apply(v); shape.attr({ transform: [['t', -x, -y], ['s', 0.01, 0.01], ['t', x, y]] }); var endState = { transform: [['t', -x, -y], ['s', 100, 100], ['t', x, y]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, animateParam.callback, animateParam.delay); } function zoomOut(shape, animateCfg, coord) { var id = shape._id; var index = shape.get('index'); var x; var y; if (coord.isPolar && shape.name !== 'point') { x = coord.getCenter().x; y = coord.getCenter().y; } else { var box = shape.getBBox(); x = (box.minX + box.maxX) / 2; y = (box.minY + box.maxY) / 2; } var v = [x, y, 1]; shape.apply(v); var endState = { transform: [['t', -x, -y], ['s', 0.01, 0.01], ['t', x, y]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, function () { shape.remove(); }, animateParam.delay); } function pathIn(shape, animateCfg) { if (shape.get('type') !== 'path') return; var id = shape._id; var index = shape.get('index'); var path = PathUtil.pathToAbsolute(shape.attr('path')); shape.attr('path', [path[0]]); var endState = { path: path }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, animateParam.callback, animateParam.delay); } function pathOut(shape, animateCfg) { if (shape.get('type') !== 'path') return; var id = shape._id; var index = shape.get('index'); var path = PathUtil.pathToAbsolute(shape.attr('path')); var endState = { path: [path[0]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, function () { shape.remove(); }, animateParam.delay); } function clipIn(shape, animateCfg, coord, startAngle, endAngle) { var clip = getClip(coord); var canvas = shape.get('canvas'); var id = shape._id; var index = shape.get('index'); var endState; if (startAngle) { clip.attr('startAngle', startAngle); clip.attr('endAngle', startAngle); endState = { endAngle: endAngle }; } else { endState = clip.endState; } clip.set('canvas', canvas); shape.attr('clip', clip); shape.setSilent('animating', true); var animateParam = getAnimateParam(animateCfg, index, id, endState); clip.animate(endState, animateParam.duration, animateParam.easing, function () { if (shape && !shape.get('destroyed')) { shape.attr('clip', null); shape.setSilent('cacheShape', null); shape.setSilent('animating', false); clip.remove(); } }, animateParam.delay); } function fadeIn(shape, animateCfg) { var id = shape._id; var index = shape.get('index'); var fillOpacity = Util.isNil(shape.attr('fillOpacity')) ? 1 : shape.attr('fillOpacity'); var strokeOpacity = Util.isNil(shape.attr('strokeOpacity')) ? 1 : shape.attr('strokeOpacity'); shape.attr('fillOpacity', 0); shape.attr('strokeOpacity', 0); var endState = { fillOpacity: fillOpacity, strokeOpacity: strokeOpacity }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, animateParam.callback, animateParam.delay); } function fadeOut(shape, animateCfg) { var id = shape._id; var index = shape.get('index'); var endState = { fillOpacity: 0, strokeOpacity: 0 }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, function () { shape.remove(); }, animateParam.delay); } function fanIn(shape, animateCfg, coord) { var angle = getAngle(shape, coord); var endAngle = angle.endAngle; var startAngle = angle.startAngle; clipIn(shape, animateCfg, coord, startAngle, endAngle); } function lineSlideLeft(shape, animateCfg, coord) { if (shape.name !== 'line') { return; } var canvas = shape.get('canvas'); var cache = shape.get('cacheShape'); var id = shape._id; var index = shape.get('index'); var clip = new G.Rect({ attrs: { x: coord.start.x, y: coord.end.y, width: coord.getWidth(), height: coord.getHeight() } }); clip.isClip = true; clip.set('canvas', canvas); var lastPath = PathUtil.pathToAbsolute(cache.attrs.path); var updatePath = PathUtil.pathToAbsolute(shape.attr('path')); var gap = lastPath[1][1] - lastPath[0][1]; // 生成过渡Path var pathPatchPosX = lastPath[lastPath.length - 1][1] + gap; var pathPatchPosY = updatePath[updatePath.length - 1][2]; var transitionPath = lastPath.concat([['L', pathPatchPosX, pathPatchPosY]]); var v = [0, 0, 1]; shape.apply(v); shape.attr('clip', clip); shape.attr('path', transitionPath); var endState = { transform: [['t', -gap, 0]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, function () { if (shape && !shape.get('destroyed')) { shape.attr('path', updatePath); shape.attr({ transform: [['t', gap, 0]] }); shape.attr('clip', null); shape.setSilent('cacheShape', null); clip.remove(); } }, animateParam.delay); } function areaSlideLeft(shape, animateCfg, coord) { if (shape.name !== 'area') { return; } var canvas = shape.get('canvas'); var cache = shape.get('cacheShape'); var id = shape._id; var index = shape.get('index'); var clip = new G.Rect({ attrs: { x: coord.start.x, y: coord.end.y, width: coord.getWidth(), height: coord.getHeight() } }); clip.isClip = true; clip.set('canvas', canvas); var lastPath = PathUtil.pathToAbsolute(cache.attrs.path); var updatePath = PathUtil.pathToAbsolute(shape.attr('path')); var gap = lastPath[1][1] - lastPath[0][1]; // 生成过渡Path var middleIndex = Math.floor(lastPath.length / 2); var pathPatchPosX = lastPath[middleIndex - 1][1] + gap; var pathPatchPosY = updatePath[middleIndex - 1][2]; var transitionPath = [].concat(lastPath.slice(0, middleIndex), [['L', pathPatchPosX, pathPatchPosY], ['L', pathPatchPosX, updatePath[middleIndex][2]]], lastPath.slice(middleIndex)); var v = [0, 0, 1]; shape.apply(v); shape.attr('clip', clip); shape.attr('path', transitionPath); var endState = { transform: [['t', -gap, 0]] }; var animateParam = getAnimateParam(animateCfg, index, id, endState); shape.animate(endState, animateParam.duration, animateParam.easing, function () { if (shape && !shape.get('destroyed')) { shape.attr('path', updatePath); shape.attr({ transform: [['t', gap, 0]] }); shape.attr('clip', null); shape.setSilent('cacheShape', null); clip.remove(); } }, animateParam.delay); } // 默认动画库 module.exports = { enter: { clipIn: clipIn, zoomIn: zoomIn, pathIn: pathIn, scaleInY: scaleInY, scaleInX: scaleInX, fanIn: fanIn, fadeIn: fadeIn }, leave: { lineWidthOut: lineWidthOut, zoomOut: zoomOut, pathOut: pathOut, fadeOut: fadeOut }, appear: { clipIn: clipIn, zoomIn: zoomIn, pathIn: pathIn, scaleInY: scaleInY, scaleInX: scaleInX, fanIn: fanIn, fadeIn: fadeIn }, update: { fadeIn: fadeIn, fanIn: fanIn, lineSlideLeft: lineSlideLeft, areaSlideLeft: areaSlideLeft } };