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>
`