CSS3,canvas,svg动画

CSS3

基础知识

transform属性
平移: translate(x,y,z)
缩放:scale(x,y,z)
旋转:rotate(x,y,z,deg)
倾斜:skew(deg,deg,deg)
坐标系:transform-origin
背面可见性:backface-visibility:visible/hidden
3D空间:transform-style:float/preserve-3d

动画

animation: 动画名称 总时长 速度 延时 播放次数 是否轮流反向播放 不播放样式
速度:linear匀速 ease低快低 ease-in低速开始 ease-out低速结束 ease-in-out低速开始和结束
播放次数:infinite/数字
不播放样式:forwards 最后样式/backwards初始样式

//平移
@keyframes tuC {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }

  40% {
    opacity: 1;
  }
  90%,
  to {
    transform: translate(40px, 20px);
    opacity: 1;
  }
}
@keyframes moveLoc1Icon1{
        0%{
          transform: translateY(-20px);
        }
        100%{
          transform: translateY(0px);
        }
      }
//旋转
@keyframes fast {
  0% {
    transform: rotateX(-33.5deg) rotateY(45deg);
  }
  40%,
  100% {
    transform: rotateX(-33.5deg) rotateY(-315deg);
  }
}
//透明度
@keyframes scaleEllipse1{
        0%{
          rx:0;
          ry:0;
          opacity: 1;
        }
        100%{
          rx:16;
          ry:8;
          opacity: 0;
        }
      }
.webpack{
animation: fast 6s ease-in-out infinite;
}

canvas

通用模板

canvas {
        background-color: rgba(255, 0, 0, 0.1);
      }
    <canvas id="tutorial" width="150" height="150">
      该浏览器不支持Canvas,请更新你的浏览器
    </canvas>
 window.onload = function () {
      draw();
    };

    // 1.当页面加载完成之后会回调该函数
    function draw() {
      // 2.拿到canvas对象
      var canvas = document.getElementById("tutorial");
      // 3.判断浏览器是否支持Canvas
      if (canvas.getContext) {
        // 4.拿到Canvas的上下文(绘图用)
        var ctx = canvas.getContext("2d");
        console.log(ctx);
      }
    }

基础知识

矩形方法:

  • fillRect(x, y, width, height): 绘制一个填充的矩形
    strokeRect(x, y, width, height): 绘制一个矩形的边框
    clearRect(x, y, width, height): 清除指定矩形区域,让清除部分完全透明。

路径方法
ctx.beginPath(); // 开始路径
// 绘图
ctx.moveTo(10, 10);
ctx.lineTo(60, 60);
ctx.lineTo(10, 110);
// ctx.closePath(); // 闭合路径
ctx.arc(x, y, r, 0, Math.PI * 2);//Math.PI * 2 一整个圆
ctx.rect(x, y, width, height)//画矩形
// 描边
ctx.strokeStyle = “red”;
ctx.stroke();
ctx.fill();//填充

样式和颜色
ctx.fillStyle = color
ctx.strokeStyle = color
ctx.fill()
ctx.stroke()

线型样式
ctx.lineWidth = value
ctx.lineCap=butt截断/round圆形/square正方形
ctx.lineJoin=round圆形/bevel斜角/miter斜槽规

绘制图片
var image = new Image();
绘制背景图片(放在最底层)
ctx.drawImage(image, 0, 0, 150, 150);
image.src = “…/images/backdrop.png”;

状态和形变
ctx.save();保存
//先进后出
ctx.restore();恢复

动画

requestAnimationFrame每秒钟回调函数执行 60 次左右
ctx.translate(x,y)移动坐标点
ctx.rotate
ctx.scale()

<style>
      body {
        padding: 0;
        margin: 0;
        background-image: url(./images/grid.png);
      }
      canvas {
        /* background-color: rgba(255, 0, 0, 0.1); */
      }
      .clock {
        width: 300px;
        height: 300px;
        margin: 10px;
        border-radius: 50px;
        background-color: black;
      }
    </style>
  </head>
  <body>
    <div class="clock">
      <canvas id="tutorial" width="300" height="300">
        该浏览器不支持Canvas,请更新你的浏览器
      </canvas>
    </div>
    <script>
      window.onload = function () {
        var canvas = document.getElementById("tutorial");
        if (canvas.getContext) {
          var ctx = canvas.getContext("2d");
        }
        requestAnimationFrame(draw);

        function draw() {
          ctx.clearRect(0, 0, 300, 300);

          ctx.save();
          ctx.translate(150, 150); // 移动坐标点(抽取)
          // 拿到时间
          var time = new Date();
          var hours = time.getHours();
          var min = time.getMinutes();
          var second = time.getSeconds();

          drawBg();
          drawText();
          drawHours(hours, min, second);
          drawMinute(hours, min, second);
          drawSecond(hours, min, second);
          drawCircle();
          drawHoursRule();
          drawMinuteRule();
          ctx.restore();

          requestAnimationFrame(draw);
        }

        function drawBg() {
          ctx.save();
          // ctx.translate(150, 150); // 移动坐标点(抽取)
          ctx.fillStyle = "white";
          ctx.beginPath();
          ctx.arc(0, 0, 130, 0, Math.PI * 2);
          ctx.fill();
          ctx.restore();
        }

        function drawText() {
          ctx.save();
          // ctx.translate(150, 150); //(抽取)
          ctx.font = "30px fangsong";
          ctx.textBaseline = "middle";
          ctx.textAlign = "center";
          //  x = Math.cos(  Math.PI * 2 / 12  * i  )  *  R
          //  y = Math.sin(  Math.PI * 2 / 12  * i  )  * R
          var timeNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
          for (var i = 0; i < 12; i++) {
            var x = Math.cos(((Math.PI * 2) / 12) * i) * 100;
            var y = Math.sin(((Math.PI * 2) / 12) * i) * 100;
            ctx.fillText(timeNumbers[i], x, y);
          }
          ctx.restore();
        }

        function drawHours(hours, min, second) {
          // 3.绘制时针
          ctx.save();
          ctx.lineWidth = 5;
          ctx.lineCap = "round";
          // ctx.translate(150, 150); //(抽取)
          // 1小时 1分 1 秒 的弧度
          // ((Math.PI * 2) / 12) * 1h => 分成 12 份
          // ((Math.PI * 2) / 12 / 60) * 1m =>分成 60份
          // ((Math.PI * 2) / 12 / 60 / 60) * 1s => 分成 60份
          ctx.rotate(
            ((Math.PI * 2) / 12) * hours +
              ((Math.PI * 2) / 12 / 60) * min +
              ((Math.PI * 2) / 12 / 60 / 60) * second
          );
          ctx.beginPath();
          ctx.moveTo(0, 0);
          ctx.lineTo(0, -50);
          ctx.stroke();
          ctx.restore();
        }

        function drawMinute(hours, min, second) {
          // 4.绘制分针
          ctx.save();
          ctx.lineWidth = 3;
          ctx.lineCap = "round";
          // ctx.translate(150, 150); //(抽取)
          // 1分 1 秒 的弧度

          // ((Math.PI * 2) / 60) * 1m =>分成60份
          // ((Math.PI * 2) / 60 / 60) * 1s => 分成 60份

          ctx.rotate(
            ((Math.PI * 2) / 60) * min + ((Math.PI * 2) / 60 / 60) * second
          );
          ctx.beginPath();
          ctx.moveTo(0, 0);
          ctx.lineTo(0, -70);
          ctx.stroke();
          ctx.restore();
        }

        function drawSecond(hours, min, second) {
          // 5.绘制秒针
          ctx.save();
          ctx.lineWidth = 2;
          ctx.lineCap = "round";
          ctx.strokeStyle = "red";
          // ctx.translate(150, 150); //(抽取)
          // 1 秒 的弧度
          // ((Math.PI * 2)  / 60) * 1s => 分成 60份
          ctx.rotate(((Math.PI * 2) / 60) * second);
          ctx.beginPath();
          ctx.moveTo(0, 0);
          ctx.lineTo(0, -90);
          ctx.stroke();
          ctx.restore();
        }

        function drawCircle() {
          // 6.绘制圆环
          ctx.save();
          // ctx.translate(150, 150);

          ctx.beginPath();
          ctx.arc(0, 0, 8, 0, Math.PI * 2);
          ctx.fill();

          ctx.beginPath();

          ctx.fillStyle = "gray";
          ctx.arc(0, 0, 5, 0, 2 * Math.PI);
          ctx.fill();
          ctx.restore();
        }

        function drawHoursRule() {
          // 7.绘制时刻度
          ctx.save();
          ctx.lineWidth = 3;
          // ctx.translate(150, 150);
          // 时的刻度
          for (var j = 0; j < 12; j++) {
            ctx.rotate(((Math.PI * 2) / 12) );
            ctx.beginPath();
            ctx.moveTo(0, -130);
            ctx.lineTo(0, -122);
            ctx.stroke();
          }
          ctx.restore();
        }

        function drawMinuteRule() {
          // 8.绘制分刻度
          ctx.save();
          ctx.lineWidth = 1;
          // ctx.translate(150, 150);
          // 时的刻度
          for (var j = 0; j < 60; j++) {
            ctx.rotate(((Math.PI * 2) / 60) * 1);
            ctx.beginPath();
            ctx.moveTo(0, -130);
            ctx.lineTo(0, -125);
            ctx.stroke();
          }
          ctx.restore();
        }
      };
    </script>
  </body>

svg

基础知识

 <svg
    width="300"
    height="300"
    xmlns="http://www.w3.org/2000/svg"
  > 
1.矩形
   <rect x="0" y="0" width="100" height="100"></rect>
   <rect x="100" y="100" width="100" height="100" rx="20" ry="20"></react>
2.圆形
 <circle cx="25" cy="75" r="20" fill="red"/>
3.椭圆
<ellipse cx="75" cy="75" rx="20" ry="5"/>
4.线条
<line x1="10" x2="50" y1="110" y2="150"/>
5.折线
<polyline points="60 110,65 120,70 115,75 130,80 125"/>
6.多边形
 <!-- 自动闭合 -->
    <polygon points="20 0, 80 50, 20 100" fill="transparent" stroke="red"></polygon>
7.三角形 M  moveTo Z  close path L  lineTo 
1.使用path 绘制一个三角形 
<path d="M 20 0, 80 50, 20 100" fill="transparent" stroke="red"></path> 
使用path 绘制一个闭合的三角形 
 <path d="M 20 0, 80 50, 20 100 Z" fill="transparent" stroke="red"></path>  
8.绘制图片
<image 
     x="0"
     y="0"
     href="../images/googlelogo_color_92x30dp.png"
     width="100"
     height="100"
    >
  </svg>
//分组
<g stroke="red" fill="transparent">
<circle r="30" cx="50" cy="100"></circle>
...
</g>
//复用<defs>包裹,不会直接显示,通常不添加属性
//复用<symbol>
//<use>引用<!-- 在这里进行图形的复用 -->
    <!-- <use href="#rectangle"></use> -->

填充和边框
stroke=“color” fill=“color”

//渐变
<linearGradient id="gradient">
<stop offset="0%" stop-color="red"></stop>
<stop offset="50%" stop-color="green"></stop>
<stop offset="100%" stop-color="blue"></stop>
</linearGradient>
<rect x="0" y="0" width="100" height="100" fill="url(#gradient)"
//毛玻璃
<fliter id="blurFilter">
<feGaussianBlur stdDeviation="8"></feGaussianBlur>
</filter>
<image href="" width="100" height="200" filter="url(#blurFilter)"></image>

动画

形变
transform=“translate(20,10) rotate(45) scale(2)”
路径描边动画
stroke-dasharray:100px//指定为虚线
stroke-dashoffset:0px//可见
SMIL动画

fill="freeze"保持最后动画状态/remove保持第一个动画状态
rotate(deg,x,y) translate(x,y) scale(x,y)

路径描边动画

.drop{
        stroke-dasharray: 200px;
        stroke-dashoffset: 200px;
        animation: lineMove 2s linear forwards;
        animation-delay: 2.5s;
      }
@keyframes lineMove{
        100%{
          /* 可见 */
          stroke-dashoffset: 0px;
        }
      }

SMIL动画

//set
<svg>
//<path id="linePath" d="M 0 100,L 100 30" fill="transparent" stoke="red"></path>
<rect>
//<set attributeName="x" from="0" to="200" begin="3s"></set>
//<animate attributeName="height" values="0;170;200" dur="3s" begin="2s" fill="freeze" repeatCount="indefinite"></animate>
//<animate attributeName="opacity" values="0;1;0"dur="1s" begin="0.2s" repeatCount="indefinite" > </animate>
//<animate attributeName="fill" values="red;green" dur="3s" begin="oneAnimate.end"  repeatCount="indefinite"></animate>
//<animateTransform attributeName="transform" type="translate" value="0 0;200 0" dur="2s" brgin="1s" repeatCount="indefinite"></animateTransform>
//<animateTransform attributeName="transform" type="rotate" from="0 150 150" to="360 150 150"  dur="2s" brgin="1s" repeatCount="indefinite"></animateTransform>
//<animateMotion path="M 0 100,L 100 30" dur="5s" rotate="auto" ></animateMotion>
<animateMotion href="#rectangle" dur="5s" rotate="auto" repeatCount="indefinite"></animateMotion>
<mpath href="#linePath"></mpath>
</rect>
</svg> 

水球体

@keyframes moveWaveBack{
        0%{
          transform: translateX(0);
        }
        100%{
          transform: translateX(50%);
        }
      }
      @keyframes moveWaveFront{
        0%{
          transform: translateX(0);
        }
        100%{
          transform: translateX(-50%);
        }
      }
window.onload = function() {
        var countEL = document.getElementById('count')
        var waterEl = document.getElementById('water')
        var currentPercentage = 0;
        var targetPercentage = 70;

        var timeId = null
        timeId = setInterval(function(){
          
          currentPercentage++; // 170
          if(currentPercentage>= targetPercentage){
            clearInterval(timeId)
          }
          countEL.innerHTML = currentPercentage

          if(currentPercentage<=100){
            waterEl.style.transform = `translateY(${100 - currentPercentage }%)`
          }
        }, 60)

      }

SVG + Snap动画

<svg id="hySvg" width="300" height="300" xmlns="http://www.w3.org/2000/svg" >
    <rect id="rectangle1" x="0" y="0" width="100" height="50"></rect>
  </svg>
<script src="./libs/snap.svg-min.js"></script>
  <script>
    window.onload = function() {
      // 1.创建一个svg
      let svg = Snap(300, 300)
      //let svg = Snap('#hySvg')
      
      // svg.paper = svg
      // console.log(svg === svg.paper) // true

      // 2.在svg画布中绘制一个圆
      // let c = svg.circle(100, 100, 50)
      //let rectangle = svg.rect(0, 100, 100, 50)
      //选择一个矩形
      //let rectangle1 = svg.select('#rectangle1')
      let c = svg.paper.circle(100, 100, 50)

      // 3.给圆添加一些属性
      c.attr({
        fill: 'red'
      })
rectangle1.hover(function() { // // 鼠标的进入
            showIcon(rectangele2)
          })
//动画的实现( requestAnimatationFrame  1s 61次)
      function showIcon(rectangele2) {
          Snap.animate(
            0.8,
            1,
            function(value) { // 30 : 0.8 -> 1
              // console.log(value)
              diagramEl.attr({
                transform: `scale(${value})`
              })
            },
            500,
            mina.bounce,
            // mina.linear,
            function() {
              console.log('动画结束')
            }
          )
        }



      // 拿到svg的元素的对象 
      // console.log(svg.node)
      // 4.将svg添加到body中
      document.body.appendChild(svg.node)
    }
  </script>

SVG + GSAP动画

<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" >
    <rect id="rectangle" x="0" y="0" width="100" height="50" fill="red"></rect>
  </svg>
  <script src="./libs/gsap.min.js"></script>
   <script>
    window.onload =function() {
     gsap.fromTo(['#rectangle'], 
         {
          scale: 0,  // 0%
           // duration: 4 // 0.5
         },
         {
           scale: 1,  // 100%
           duration: 2, // 0.5
           repeat:1,
         })
         //时间线
         
      let timeline = gsap.timeline() // 动画时间线

     timeline.to(['#rectangle1', '#rectangle2'], {
        scale: 0.5,
        duration: 1
      })

      // .to('#rectangle2', {
      //   scale: 0.5,
      //   duration: 1,
      // })

      .to('#rectangle3', {
        scale: 0.5,
        duration: 1,
      })


       timeline2.from(
        [
        '#wheel1', // begin= 0s
        '#wheel2', // 0.2
        '#wheel3', // 0.4
        '#wheel4' // 0.6
        ], 
        {
        scaleX: 0,
        scaleY: 0,
        duration: 1,
        transformOrigin: 'center',
        ease: 'bounce.out',
        stagger: 0.2
      })
      .from(
        [
          "#footboard1",
          "#footboard2"
        ]
        , {
          scaleX: 0,
          duration: 1,
          transformOrigin: 'left',
          ease: 'bounce.out',
        })
    }
   </script>
`
  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值