Commit ab509a01 authored by JetLu's avatar JetLu 🚴🏻

🍄

parents
Pipeline #69889 failed with stages
in 0 seconds
{
"presets": [
["@babel/env"]
],
"plugins": [
"@babel/proposal-class-properties",
"@babel/proposal-export-default-from",
["@babel/transform-runtime", {
"corejs": false,
"helpers": false,
"regenerator": true
}]
]
}
\ No newline at end of file
node_modules
dist
package-lock.json
\ No newline at end of file
{
"name": "tween",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --host 0.0.0.0",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "JetLu",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-export-default-from": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/runtime": "^7.0.0",
"babel-loader": "^8.0.2",
"css-loader": "^1.0.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"mathjs": "^5.1.2",
"style-loader": "^0.23.0",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.7"
}
}
import {catmulRom, bezier} from './core'
HTMLElement.prototype.on = function(...args) {
this.addEventListener(...args)
return this
}
document.body.on('pointerdown', ev => {
const target = ev.target
if (target.classList.contains('dot')) {
console.log(JSON.parse(target.dataset.position))
target.remove()
} else if (target === document.body) {
const
dot = document.createElement('div'),
{pageX: x, pageY: y} = ev
dot.classList.add('dot')
dot.style.top = `${y}px`
dot.style.left = `${x}px`
dot.dataset.position = JSON.stringify({x, y})
document.body.appendChild(dot)
} else if (target.classList.contains('btn-run')) {
target.classList.contains('bezier') ? run('bezier') : run('catmulRom')
} else if (target.classList.contains('btn-clear')) {
clear()
}
})
async function run(action) {
const
dots = document.querySelectorAll('.dot'),
player = document.querySelector('.player')
document.querySelectorAll('.mini-dot').forEach(child => child.remove())
document.querySelector('.player').setAttribute('style', '')
if (action === 'catmulRom') {
if (dots.length < 1) return alert('至少 1 个点吧!')
const points = Array.prototype.map.call(dots, dot => JSON.parse(dot.dataset.position))
points.unshift(
{x: player.offsetLeft, y: player.offsetTop},
{x: player.offsetLeft, y: player.offsetTop}
)
points.push(points[points.length - 1])
for (let i = 0; i + 3 < points.length; i++) {
const
p1 = points[i],
p2 = points[i + 1],
p3 = points[i + 2],
p4 = points[i + 3],
delta = 10 / distance(p2, p3)
await animateCatmulRom(p1, p2, p3, p4, delta)
}
} else {
if (dots.length < 2) return alert('至少 2 个点吧!')
const points = Array.prototype.map.call(dots, dot => JSON.parse(dot.dataset.position))
points.unshift({x: player.offsetLeft, y: player.offsetTop})
for (let i = 0; i + 2 < points.length; i++) {
const
p1 = points[i],
p2 = points[i + 1],
p3 = points[i + 2],
delta = 10 / distance(p2, p3)
await animateBezier(p1, p2, p3, delta)
}
}
}
function animateBezier(p1, p2, p3, delta) {
const player = document.querySelector('.player')
return new Promise(resolve => {
let t = 0
loop()
function loop() {
t > 1 ? t = 1 : t += delta
const
{x, y} = bezier(t, p1, p2, p3),
dot = document.createElement('i')
dot.classList.add('mini-dot')
player.style.left = `${x}px`
player.style.top = `${y}px`
dot.style.left = player.style.left
dot.style.top = player.style.top
document.body.appendChild(dot)
t == 1 ? resolve() : requestAnimationFrame(loop)
}
})
}
function animateCatmulRom(p1, p2, p3, p4, delta) {
const player = document.querySelector('.player')
return new Promise(resolve => {
let t = 0
loop()
function loop() {
t > 1 ? t = 1 : t += delta
const
{x, y} = catmulRom(t, p1, p2, p3, p4),
dot = document.createElement('i')
dot.classList.add('mini-dot')
player.style.left = `${x}px`
player.style.top = `${y}px`
dot.style.left = player.style.left
dot.style.top = player.style.top
document.body.appendChild(dot)
t == 1 ? resolve() : requestAnimationFrame(loop)
}
})
}
function clear() {
document.querySelectorAll('.dot').forEach(child => child.remove())
document.querySelectorAll('.mini-dot').forEach(child => child.remove())
document.querySelector('.player').setAttribute('style', '')
}
function distance(a, b) {
return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2)
}
export default function (t, p1, p2, p3) {
return {
x: calc(t, p1.x, p2.x, p3.x),
y: calc(t, p1.y, p2.y, p3.y)
}
}
function calc(t, i1, i2, i3) {
return (1 - t) ** 2 * i1 + 2 * (1 - t) * t * i2 + t ** 2 * i3
}
\ No newline at end of file
export default function(t, p1, p2, p3, p4) {
return {
x: calc(t, p1.x, p2.x, p3.x, p4.x),
y: calc(t, p1.y, p2.y, p3.y, p4.y)
}
}
function calc(t, i1, i2, i3, i4) {
const
a = [t ** 3, t ** 2, t, 1],
b = [[-.5, 1.5, -1.5, .5], [1, -2.5, 2, -.5], [-.5, 0, .5, 0], [0, 1, 0, 0]],
c = [[i1], [i2], [i3], [i4]]
return mathjs.multiply(a, b, c)[0]
}
\ No newline at end of file
export catmulRom from './catmulRom'
export bezier from './bezier'
\ No newline at end of file
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
position: relative;
.player {
@size: 4rem;
position: absolute;
width: @size;
height: @size;
border-radius: @size / 2;
background-color: #fc3;
top: 50%;
left: @size;
transform: translate(-50%, -50%);
}
.dot {
@size: 1rem;
width: @size;
height: @size;
border-radius: @size / 2;
background-color: #f3c;
position: absolute;
transform: translate(-50%, -50%);
}
.mini-dot {
@size: .5rem;
width: @size;
height: @size;
border-radius: @size / 2;
background-color: #6cffb5;
position: absolute;
transform: translate(-50%, -50%);
}
}
.btn-group {
display: flex;
button {
// -webkit-appearance: none;
border: none;
color: #fff;
background-color: #007BFF;
font-size: 1rem;
padding: .5rem 1rem;
border-radius: .3rem;
margin-right: 1rem;
cursor: pointer;
}
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Curve</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdnjs.cloudflare.com/ajax/libs/eruda/1.4.4/eruda.min.js"></script>
<script>//eruda.init()</script>
</head>
<body>
<div class="player"></div>
<section class="btn-group">
<button class="btn-clear">Clear</button>
<button class="btn-run bezier">Run Bezier</button>
<button class="btn-run catmul-rom">Run CatmulRom</button>
</section>
</body>
</html>
\ No newline at end of file
const
path = require('path'),
htmlWebpackPlugin = require('html-webpack-plugin'),
webpack = require('webpack')
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
entry: [
'./src/index.less',
'./src/app.js'
],
output: {
path: path.resolve('dist'),
filename: 'game.js'
},
devServer: {
hot: true,
contentBase: '.'
},
devtool: isProd ? false : 'source-map',
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
exclude: /node_modules/
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
}
]
},
plugins: [
new htmlWebpackPlugin({
template: './src/template.html',
hash: true,
filename: 'index.html',
inject: 'body',
minify: {
collapseWhitespace: true
}
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.ProvidePlugin({
PIXI: 'pixi.js',
mathjs: 'mathjs'
})
],
mode: isProd ? 'production' : 'development'
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment