<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/animejs/3.2.0/anime.min.js"></script>
<style>
#icon{
width:50px;
height:50px;
background: red;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<svg style="width:100vw;height:100vh" id="svg">
<path style="fill: none; stroke: black; stroke-width: 1;"
id="path"
></path>
</svg>
<div id="icon">
</div>
<script>
;(function() {
const $body = document.querySelector('body')
const $svgEl = document.querySelector("#svg")
const $path = document.querySelector('#path')
const $path2 = document.querySelector('#path2')
window.addEventListener('mousedown', () => {
$path.setAttribute('d', '')
const points = []
function draw(e) {
const x = e.pageX
const y = e.pageY
points.push(x, y)
if (points.length >= 10) {
const pathString = solve(points, 1.5)
$path.setAttribute('d', pathString)
}
// const path2String=solve([667,93,312,117,249,339],1.5)
// $path2.setAttribute('d',path2String)
// 利用生成的曲线确实是很平滑的。说明这个函数没问题,还是现在的点太密了,或者还是需要拟合操作
}
window.addEventListener('mousemove', draw)
window.addEventListener('mouseup', () => {
if (points.length >= 10) {
runAnimation($path.getAttribute('d'))
}
points.length = 0
window.removeEventListener('mousemove', draw)
})
})
/**
* 将折线修改为圆滑曲线
* @param {*} data [x1,y1,x2,y2,x3,y3...] 长度必须大于4, 长度必须是偶数
* @param {*} k 拟合系数, 数字
*/
function solve(data, k =1) {
const size = data.length
const last = size - 4
let path = `M${data[0]},${data[1]}`
for (let i = 0; i < size - 2; i += 2) {
const x0 = i ? data[i - 2] : data[0]
const y0 = i ? data[i - 1] : data[1]
// 第一个点
const x1 = data[i + 0]
const y1 = data[i + 1]
//第二个点
// x2 和 y2 作为终点坐标
const x2 = data[i + 2]
const y2 = data[i + 3]
const x3 = i !== last ? data[i + 4] : x2
const y3 = i !== last ? data[i + 5] : y2
// 计算控制点
const cp1x = x1 + ((x2 - x0) / 6) * k
const cp1y = y1 + ((y2 - y0) / 6) * k
const cp2x = x2 - ((x3 - x1) / 6) * k
const cp2y = y2 - ((y3 - y1) / 6) * k
path += ` C${cp1x},${cp1y},${cp2x},${cp2y},${x2},${y2}`
}
return path
}
/**
* @description 运行动画
* @date 2019-08-23
* @param {*} path
*/
function runAnimation() {
// 设置移动点样式
const path=anime.path('#path')
console.log(path)
anime({
targets:'#icon',
translateX:path('x'),
translateY:path('y'),
rotate:path('angle'),
// 因为这样形成的曲线的太不平滑,所以需要去掉角度旋转。感觉还是要优化下算法吗,或者采用点生成曲线的方法
// 需要曲线拟合。
easing:'linear',
duration:9000,
loop:true,
})
}
})()
</script>
</body>
</html>
网友评论