23 动画

作者: skoll | 来源:发表于2022-01-18 09:46 被阅读0次

    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>
    

    相关文章

      网友评论

          本文标题:23 动画

          本文链接:https://www.haomeiwen.com/subject/jcwchrtx.html