<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas画板钢笔绘制线条特效</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
background: black;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: 14px;
color: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
canvas {
position: fixed;
width: 100%;
height: 100%;
}
footer {
position: fixed;
right: 0;
top: 0;
right: 0;
padding: 10px 10px;
text-align: right;
width: 240px;
}
a {
display: inline-block;
margin-left: 2px;
padding: 2px 4px;
color: rgba(52, 52, 54, 1);
text-decoration: none;
background-color: #fcd000;
border-radius: 4px;
opacity: 1;
-webkit-transition: opacity 0.2s;
transition: opacity 0.2s;
}
img {
width: 300px;
max-width: 30%;
position: fixed;
-webkit-transform: translate3d(0%, -50%, 0px);
transform: translate3d(0%, -50%, 0px);
top: 50%;
left: 50%;
pointer-events: none;
}
section {
-webkit-transition: 0.4s ease;
transition: 0.4s ease;
opacity: 0;
visibility: hidden;
will-change: opacity, visibility;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
button {
-webkit-appearance: none;
padding: 12px 24px;
border-radius: 0;
position: fixed;
left: 50%;
bottom: 24px;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
text-transform: uppercase;
letter-spacing: 2px;
color: white;
background: black;
border: 1px solid white;
cursor: none;
}
.output button {
cursor: pointer;
}
button:focus,
button:hover {
color: black;
background: white;
}
.input {
cursor: none;
opacity: 1;
visibility: visible;
}</style>
</head>
<body>
<link rel="stylesheet" href="css/normalize.min.css">
<section class="input" style="opacity: 1; visibility: visible;">
<canvas></canvas>
<button class="create">创建粒子</button>
<img src="css/pen.svg" />
</section>
<section class="output">
<canvas></canvas>
<button class="reset">重置</button>
</section>
<script>
!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):n.starlings=r()}(this,function(){"use strict";return function(n,r,t,o,e,u,i,f){var a=f.onSetup;void 0===a&&(a=null);var v=f.onRepeat;void 0===v&&(v=null);var c=f.modifier;void 0===c&&(c=null);var l=f.perspective;void 0===l&&(l=1);var d=f.pixelRatio;void 0===d&&(d=1);var m=f.triangles;void 0===m&&(m=!1);var s,p,y=r.length,w=function(n,r){var t=s.createShader(n);return s.shaderSource(t,r),s.compileShader(t),t},b=function(){for(var n=0;n<o.length;n+=1){for(var r=s.createBuffer(),e=o[n],u=e.data(0,0).length,i=new Float32Array(t*y*u),f=0;f<t;f+=1)for(var a=e.data(f,t),v=f*y*u,l=0;l<y;l+=1)for(var d=0;d<u;d+=1)null!==c&&e.name===c.attribute?i[v]=c.value(i[v],a,d,l):i[v]=a[d],v+=1;s.bindBuffer(s.ARRAY_BUFFER,r),s.bufferData(s.ARRAY_BUFFER,i,s.STATIC_DRAW);var m=s.getAttribLocation(p,o[n].name);s.enableVertexAttribArray(m),s.vertexAttribPointer(m,u,s.FLOAT,!1,!1,0,0)}},A=function(){e.push({name:"uMVP",type:"mat4"});for(var n=0;n<e.length;n+=1){var r=s.getUniformLocation(p,e[n].name);e[n].location=r}},F={float:function(n,r){return s.uniform1f(n,r)},vec2:function(n,r){return s.uniform2fv(n,r)},vec3:function(n,r){return s.uniform3fv(n,r)},vec4:function(n,r){return s.uniform4fv(n,r)},mat2:function(n,r){return s.uniformMatrix2fv(n,!1,r)},mat3:function(n,r){return s.uniformMatrix3fv(n,!1,r)},mat4:function(n,r){return s.uniformMatrix4fv(n,!1,r)}},g=function(){s.clear(16640),s.useProgram(p),null!==v&&v(s,p,e);for(var n=0;n<e.length;n+=1)F[e[n].type](e[n].location,e[n].value);s.drawArrays(m?s.TRIANGLES:s.POINTS,0,y*t),requestAnimationFrame(g)},h=function(){n.width=n.clientWidth*d,n.height=n.clientHeight*d;var r=s.drawingBufferWidth,t=s.drawingBufferHeight;s.viewport(0,0,r,t),e[e.length-1].value=[l/(r/t),0,0,0,0,l,0,0,0,0,-1,-1,0,0,1,1]};s=n.getContext("webgl"),p=s.createProgram(),s.attachShader(p,w(s.VERTEX_SHADER,u)),s.attachShader(p,w(s.FRAGMENT_SHADER,i)),s.linkProgram(p),A(),h(),b(),null!==a&&a(s),g(),window.addEventListener("resize",h,!1)}});
'use strict';
var segments = [];
var points = [];
var input = document.querySelector('.input');
var output = document.querySelector('.output');
// Input
{
(function () {
var canvas = input.querySelector('canvas');
var image = input.querySelector('img');
var context = canvas.getContext('2d');
canvas.width = canvas.clientWidth * window.devicePixelRatio;
canvas.height = canvas.clientHeight * window.devicePixelRatio;
context.lineWidth = window.devicePixelRatio === 1 ? 1 : 3;
context.strokeStyle = '#FEFEFE';
var current = [];
var hold = false;
var midPointBtw = function midPointBtw(p1, p2) {
return {
x: p1.x + (p2.x - p1.x) / 2,
y: p1.y + (p2.y - p1.y) / 2
};
};
var getCoordinatesFromEvent = function getCoordinatesFromEvent(event) {
var touch = typeof event.changedTouches !== 'undefined';
return {
x: touch ? event.changedTouches[0].clientX : event.clientX,
y: touch ? event.changedTouches[0].clientY : event.clientY
};
};
var drawSegments = function drawSegments(event) {
var coords = getCoordinatesFromEvent(event);
current.push({
x: coords.x * window.devicePixelRatio,
y: coords.y * window.devicePixelRatio
});
context.beginPath();
context.moveTo(current[0].x, current[0].y);
for (var i = 0; i < current.length - 1; i += 1) {
var midPoint = midPointBtw(current[i], current[i + 1]);
context.quadraticCurveTo(current[i].x, current[i].y, midPoint.x, midPoint.y);
}
context.stroke();
};
var start = function start(event) {
var coords = getCoordinatesFromEvent(event);
hold = true;
current = [{
x: coords.x * window.devicePixelRatio,
y: coords.y * window.devicePixelRatio
}];
};
var move = function move(event) {
var coords = getCoordinatesFromEvent(event);
image.style.left = '0px';
image.style.top = '0px';
image.style.transform = 'translate3d(' + coords.x + 'px, ' + coords.y + 'px, 0)';
if (hold) drawSegments(event);
};
var end = function end() {
hold = false;
segments.push(current);
};
canvas.addEventListener('mousedown', start);
canvas.addEventListener('touchstart', start);
input.addEventListener('mousemove', move);
input.addEventListener('touchmove', move);
canvas.addEventListener('mouseup', end);
canvas.addEventListener('touchend', end);
})();
}
// Output
{
(function () {
var canvas = output.querySelector('canvas');
var initialize = function initialize() {
var pixelRatio = window.devicePixelRatio;
var multiplier = points.length;
var duration = 0.4;
var geometry = [{ x: 0, y: 0, z: 0 }];
var pointSize = 4..toFixed(1);
var step = 0;
setTimeout(function () {
step = 0.004;
}, 400);
var offset = 0.5;
var attributes = [{
name: 'aPositionStart',
data: function data(i, total) {
return [points[i].x, points[i].y, 0
评论0