23 动画
2022-01-18 本文已影响0人
skoll
css动画
1 .css定义一些动画样式
@keyframes running-line {
to {
stroke-dashoffset: -1000;
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
2 .直接和本来的css样式定义
.node.running .status img {
animation: spin 1s linear infinite;
}
3 .x6操作属性发生动画,transition动画
graph.on('edge:click',(e)=>{
console.log('click',e)
e.e.stopPropagation()
const t=e.edge.attr('c1/atConnectionRatio')>0.3?0.3:0.9
//获取data,attrs里面的某个属性值,
//并且重新搞成一个新的值
//动画配置
const options={
delay:100,
duration:1000,
timing:X6.Timing.easeInOutBack,
}
e.edge.transition('attrs/c1/atConnectionRatio',t,options)
//元素.变化的属性,变化后的值,变化的参数
e.edge.transition('attrs/c2/atConnectionRatio',t,options)
})
const polygon = graph.addNode({
shape: 'polygon',
x: 200,
y: 140,
width: 80,
height: 80,
points:
'26.934,1.318 35.256,18.182 53.867,20.887 40.4,34.013 43.579,52.549 26.934,43.798 10.288,52.549 13.467,34.013 0,20.887 18.611,18.182',
attrs: {
body: {
stroke: 'none',
},
},
})
const view = graph.findView(polygon)
if (view) {
view.animate('polygon', {
// attributeType: 'XML',
attributeName: 'fill',
values: '#eee;#000',
dur: '2s',
repeatCount: 'indefinite',
})
}
const source = graph.addNode({
x: 120,
y: 40,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
},
},
})
source.transition('angle',360,{
delay:1000,
duration:1000,
})
4 .path路线动画
const graph=new X6.Graph({
container:document.getElementById('container'),
width:800,
height:600,
grid:true,
})
X6.Graph.registerConnector(
'line1',
(sourcePoint,targetPoint,vertices,args)=>{
console.log('sourcePoint',sourcePoint)
console.log('targetPoint',targetPoint)
console.log('vertices',vertices)
console.log('args',args)
//这个函数还会自动获取已经传的参数,那就是说他的原函数一定是在这个上面
//这里生成线段
const spread=args.spread||20
//没有传值,取默认的20
const points=[...vertices,targetPoint].map((p=>X6.Point.create(p)))
//拿到所有需要计算的点.中间的点和最后的点
const path=new X6.Path()
let prev=X6.Point.create(sourcePoint)
//创建一个路径点
console.log(prev)
//初始化一条新的路径:关键是这些没有文档啊啊啊.只能猜测大概的api
path.appendSegment(X6.Path.createSegment('M',prev))
for(let i=0;i<points.length;i++){
//const next=points[i]
//path.appendSegment(X6.Path.createSegment('L',next))
//最简单的实现,把给的节点全都加到连线里面,现在是不做路上的其他拐点线条而已
let next=points[i]
//path.appendSegment(X6.Path.createSegment('L',next))
const distance=prev.distance(next)
//算下当前的和下一个的距离
let d=spread
//每次加的幅度
while(d<distance){
const current=prev.clone().move(next,-d)
//当前的点
current.translate(
Math.floor(7*Math.random())-3,
Math.floor(7*Math.random())-3
)
//当前的点随便换一个位置
path.appendSegment(X6.Path.createSegment('L',current))
d+=spread
}
prev=next
//一开始不知道每次都是随机,最后是怎么对上最后的基准点呢,其实很简单,最后一个点是固定的,也就是说就算是倒数第一个点偏到姥姥家,也能连的上
}
return path
},true
)
const source = graph.addNode({
x: 120,
y: 40,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
},
},
})
const target = graph.addNode({
x: 400,
y: 260,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
},
},
})
const path=graph.addEdge({
target:target,
source:source,
vertices: [
{ x: 200, y: 200 },
{ x: 380, y: 120 },
],
attrs:{
line:{
stroke:"#722ed1"
}
},
connector:{
name:'line1',
args:{
spread:10,
}
}
})
const view=graph.findViewByCell(path)
console.log(view)
if(view){
const path=view.findOne('path')
if(path){
const token=X6.Vector.create('circle',{
r:6,
fill:"#5F95FF"
})
token.animateAlongPath(
{
dur:'5s',
repeatCount:'indefinite'
},
path,
)
token.appendTo(path.parentNode)
}
}
5 .元素动画CellView上的animation方法指定元素的某个属性变化过程
const view=graph.findView(source)
if(view){
view.animate('rect',{
attributeName:'x',
from:40,
to:120,
dur:'10s',
repeatCount:'indefinite',
})
view.animate('rect',{
attributeName:'fill',
from:'red',
to:'green',
dur:'1s',
repeatCount:'indefinite',
})
}
6 .animationTransform:和css Transform一样的效果
1 .文档 https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateTransform
2 .rotation(theta, x, y),theta是一个角度,x和y是绝对坐标
const source = graph.addNode({
x: 120,
y: 40,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
},
},
})
const view=graph.findView(source)
if(view){
view.animateTransform('rect',{
attributeName:'transform',
type:'rotate',
from:'0 0 0',
to:'360 0 10',
dur:'3s',
repeatCount:'indefinite'
})
}
7 .沿边运动
1 .沿着边运动,表示流程.比如一个箭头沿着线操作
2 .
animation属性
1 .path:路径.就是要操作的元素,第一个参数就是
2 .target:第一个参数选到的属性值.
3 .options
1 .delay:动画延迟多久之后开始
2 .duration:动画持续时间
3 .timing:定时函数.'linear'.https://x6.antv.vision/zh/docs/tutorial/advanced/animation#%E5%BC%80%E5%A7%8B
4 .interp:插值函数
5 .start:动画开始的回调
6 .progress:动画执行过程中的回调
7 .complete:动画执行完毕的回调函数
8 .stop:动画被停止的回调函数
9 .finish:动画执行完成或被停止时的回调函数.
10 .jumpedToEnd:手动停止动画时,是否立即将动画完成
11 .
SVG animation 参数详解
1 .attributeName:要变化的元素属性名称.比如position的x,opacity,font-size
2 .attributeType="CSS|XML|auto"
1 .表示attributeName属性值的列表
2 .x,y,transform就属于XML.
3 .opacity属于CSS
4 .auto表示默认,自动判别.一般不知道的时候直接用auto
5 .某些属性font-size,xml和css都能起作用,这个时候就需要明确归属
3 .from,to,by,values
1 .from:动画的起始值
2 .to:动画的结束值
3 .by:动画的相对变化值
4 .values:用分号分隔的一个或者多个值,可以看出动画有多少个关键值点
注意值
1 .如果动画的起始值和默认值一样,from参数可以省略
2 .to和by至少要出现一个,否则没有效果.to表示变化的绝对值.如果值是100表示变化到100,by表示相对值,值是100,那么表示变化到100+原来的值
3 .to,by同时出现,只会取to得值
4 .values:有过渡需求的时候就要这个
<svg width="320" height="200" xmlns="http://www.w3.org/2000/svg">
<text font-family="microsoft yahei" font-size="120" y="150" x="160">
马
<animate attributeName="x" values="160;40;160" dur="3s" repeatCount="indefinite" />
</text>
</svg>
5 .后面属性太多了,用到再说吧.
总结
1 .看来就是,所有的动画都是基于svg的动画原生实现的,好像没有啥高级的东西.所以如果不支持svg动画,这些也爆炸.
2 .https://www.zhangxinxu.com/wordpress/2014/08/so-powerful-svg-smil-animation/?shrink=1 具体的使用方法
3 .看来这里面好多属性,这里都不支持
延边动画.除了path动画,另一种需要的掌握的动画操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://unpkg.com/@antv/x6/dist/x6.js"></script>
</head>
<body>
<h3>基本图形和属性</h3>
<div id="container">
</div>
<script>
const graph=new X6.Graph({
container:document.getElementById('container'),
width:800,
height:600,
grid:true,
})
const a = graph.addNode({
x: 50,
y: 50,
width: 100,
height: 40,
label: 'A',
})
const b = graph.addNode({
x: 250,
y: 50,
width: 100,
height: 40,
label: 'B',
})
const c = graph.addNode({
x: 350,
y: 150,
width: 100,
height: 40,
label: 'C',
})
const d = graph.addNode({
x: 80,
y: 240,
width: 100,
height: 40,
label: 'D',
})
graph.addEdge({
source: a,
target: b,
})
graph.addEdge({
source: b,
target: c,
})
graph.addEdge({
source: b,
target: d,
connector: 'smooth',
attrs: {
line: {
strokeDasharray: '5 5',
},
},
})
//闪烁动画
function flash(cell){
const cellView=graph.findViewByCell(cell)
if(cellView){
cellView.highlight()
setTimeout(()=>cellView.unhighlight(),300)
}
}
let manual=false
graph.on('node:click',({cell})=>{
flash(cell)
//节点点击闪烁
manual=true
graph.trigger('signal',cell)
//触发一个事件
})
graph.on('signal',(cell)=>{
//接收到上面触发的事件,也就是说这里起始可以定义任意名字,你自己需要的事件的.
if(cell.isEdge()){
//如果是边的话,就触发动画
const view=graph.findViewByCell(cell)
//找到边的视图,对应图里面
const circle=X6.Vector.create('circle',{r:5,fill:'#feb662'})
//这仅仅是用来生成一个图形,而不是节点,猜测可能一个节点拥有的额外属性比较少,更加轻量级
const target=cell.getTargetCell()
console.log(target,'target')
setTimeout(()=>{
view.sendToken(circle.node,1000,()=>{
//边的一个动画函数
//1 .沿边运动的元素或元素选择器
if(target){
//当前动画执行完毕之后,继续下一个节点的世界触发.
graph.trigger('signal',target)
}
})
},300)
}else{
//如果是点的话,就继续向下找,然后触发.
flash(cell)
const edges=graph.model.getConnectedEdges(cell,{
outgoing:true,
})
//找相连的所有边
edges.forEach((edge)=>graph.trigger('signal',edge))
}
})
</script>
</body>
</html>