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>
上一篇下一篇

猜你喜欢

热点阅读