Live demo: http://thepoint.surge.sh
Include a suedebrush.png file that you want to use as your suede texture
Live demo: http://thepoint.surge.sh
Include a suedebrush.png file that you want to use as your suede texture
<html> | |
<head> | |
<meta name="apple-mobile-web-app-capable" content="yes" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.0.0/pixi.min.js"></script> | |
<link rel="stylesheet" type="text/css" href="main.css"> | |
</head> | |
<body> | |
</body> | |
<script src="victor.js"></script> | |
<script src="index.js"></script> | |
</html> |
(function() { | |
function random(a, b) { | |
return Math.floor(Math.random()*(b-a+1)+a); | |
} | |
var SIZE = [1080, 1920]; | |
var HEIGHT; | |
var WIDTH; | |
var RATIO = SIZE[0] / SIZE[1]; | |
var RENDERER = PIXI.autoDetectRenderer(SIZE[0], SIZE[1], { | |
backgroundColor: 0xFF4968 | |
}); | |
var STAGE = new PIXI.Container(0xFFFFFF, true); | |
// var ROOT_DIRECTION = new Victor(random(-20, 20), random(-20, 20)); | |
var ROOT_DIRECTION = new Victor(0.5, -1); | |
function initialize() { | |
document.body.appendChild(RENDERER.view); | |
window.STAGE = STAGE; | |
STAGE.interactive = true; | |
var circle = new PIXI.Graphics(); | |
STAGE.addChild(circle); | |
var interactionManager = new PIXI.interaction.InteractionManager(RENDERER); | |
var isMousedown; | |
var previousX = 0; | |
var previousY = 0; | |
function onDown() { | |
isMousedown = true; | |
previousX = this.eventData.data.global.x; | |
previousY = this.eventData.data.global.y; | |
}; | |
function onMove() { | |
if(isMousedown) { | |
var newX = this.eventData.data.global.x; | |
var newY = this.eventData.data.global.y; | |
var deltaX = newX - previousX; | |
var deltaY = newY - previousY; | |
if(Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) { | |
var direction = new Victor(newX - previousX, newY - previousY).normalize(); | |
var angle = ROOT_DIRECTION.angle() - direction.angle(); | |
var color; | |
if(Math.abs(angle) < 0.75) { // erase | |
color = 0xFF4968; | |
var brush = PIXI.Sprite.fromImage('suedebrush.png'); | |
brush.tint = color; | |
brush.position.x = newX; | |
brush.position.y = newY; | |
brush.anchor.x = 0.5; | |
brush.anchor.y = 0.5; | |
brush.alpha = angle + 0.5; | |
brush.rotation = random(1, 3); | |
STAGE.addChild(brush); | |
} else { // paint | |
color = 0xDC3E59; | |
var brush = PIXI.Sprite.fromImage('suedebrush.png'); | |
brush.tint = color; | |
brush.position.x = newX; | |
brush.position.y = newY; | |
brush.anchor.x = 0.5; | |
brush.anchor.y = 0.5; | |
brush.rotation = random(1, 3); | |
STAGE.addChild(brush); | |
} | |
} | |
previousX = newX; | |
previousY = newY; | |
} | |
}; | |
function onUp() { | |
isMousedown = false; | |
}; | |
interactionManager | |
.on('mousedown', onDown) | |
.on('mousemove', onMove) | |
.on('mouseup', onUp) | |
.on('touchstart', onDown) | |
.on('touchmove', onMove) | |
.on('touchend', onUp); | |
var modifierX = window.devicePixelRatio * 2; | |
var modifierY; | |
if(window.devicePixelRatio == 1) { | |
modifierY = window.devicePixelRatio * 0.9; | |
} else if(window.devicePixelRatio == 2 || window.devicePixelRatio < 3) { | |
modifierY = 2.5; | |
} else if(window.devicePixelRatio >= 3) { | |
modifierY = 2.3; | |
} | |
for(var i=0; i<500; i++) { | |
var brush = PIXI.Sprite.fromImage('suedebrush.png'); | |
var color = 0xDC3E59; | |
brush.tint = color; | |
brush.position.x = random(0, WIDTH * modifierX); | |
brush.position.y = random(HEIGHT * 0.1 * window.devicePixelRatio, HEIGHT * modifierY); | |
brush.anchor.x = 0.5; | |
brush.anchor.y = 0.5; | |
brush.rotation = random(1, 16); | |
STAGE.addChild(brush); | |
} | |
}; | |
function animate() { | |
requestAnimationFrame(animate); | |
RENDERER.render(STAGE); | |
}; | |
animate(); | |
function resize() { | |
if(window.innerWidth / window.innerHeight >= RATIO) { | |
WIDTH = window.innerHeight * RATIO; | |
HEIGHT = window.innerHeight; | |
} else { | |
WIDTH = window.innerWidth; | |
HEIGHT = window.innerWidth / RATIO; | |
} | |
RENDERER.view.style.width = WIDTH + 'px'; | |
RENDERER.view.style.height = HEIGHT + 'px'; | |
}; | |
window.onresize = resize; | |
resize(); | |
initialize(); | |
})(); |
body { | |
margin: 0; | |
background: #3a3a3a; | |
text-align: center; | |
display: flex; | |
align-items: center; | |
-webkit-transform: translate3d(0,0,0); | |
-moz-transform: translate3d(0,0,0); | |
transform: translate3d(0,0,0); | |
} | |
canvas { | |
margin: 0 auto; | |
} |
/*! | |
MIT License | |
Copyright (c) 2011 Max Kueng, George Crabtree | |
Permission is hereby granted, free of charge, to any person obtaining | |
a copy of this software and associated documentation files (the | |
"Software"), to deal in the Software without restriction, including | |
without limitation the rights to use, copy, modify, merge, publish, | |
distribute, sublicense, and/or sell copies of the Software, and to | |
permit persons to whom the Software is furnished to do so, subject to | |
the following conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
!function(t){if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else{var i;"undefined"!=typeof window?i=window:"undefined"!=typeof global?i=global:"undefined"!=typeof self&&(i=self),i.Victor=t()}}(function(){return function t(i,r,n){function o(s,h){if(!r[s]){if(!i[s]){var u="function"==typeof require&&require;if(!h&&u)return u(s,!0);if(e)return e(s,!0);throw new Error("Cannot find module '"+s+"'")}var p=r[s]={exports:{}};i[s][0].call(p.exports,function(t){var r=i[s][1][t];return o(r?r:t)},p,p.exports,t,i,r,n)}return r[s].exports}for(var e="function"==typeof require&&require,s=0;s<n.length;s++)o(n[s]);return o}({1:[function(t,i,r){function n(t,i){return this instanceof n?(this.x=t||0,void(this.y=i||0)):new n(t,i)}function o(t,i){return Math.floor(Math.random()*(i-t+1)+t)}function e(t){return t*h}function s(t){return t/h}r=i.exports=n,n.fromArray=function(t){return new n(t[0]||0,t[1]||0)},n.fromObject=function(t){return new n(t.x||0,t.y||0)},n.prototype.addX=function(t){return this.x+=t.x,this},n.prototype.addY=function(t){return this.y+=t.y,this},n.prototype.add=function(t){return this.x+=t.x,this.y+=t.y,this},n.prototype.addScalar=function(t){return this.x+=t,this.y+=t,this},n.prototype.addScalarX=function(t){return this.x+=t,this},n.prototype.addScalarY=function(t){return this.y+=t,this},n.prototype.subtractX=function(t){return this.x-=t.x,this},n.prototype.subtractY=function(t){return this.y-=t.y,this},n.prototype.subtract=function(t){return this.x-=t.x,this.y-=t.y,this},n.prototype.subtractScalar=function(t){return this.x-=t,this.y-=t,this},n.prototype.subtractScalarX=function(t){return this.x-=t,this},n.prototype.subtractScalarY=function(t){return this.y-=t,this},n.prototype.divideX=function(t){return this.x/=t.x,this},n.prototype.divideY=function(t){return this.y/=t.y,this},n.prototype.divide=function(t){return this.x/=t.x,this.y/=t.y,this},n.prototype.divideScalar=function(t){return 0!==t?(this.x/=t,this.y/=t):(this.x=0,this.y=0),this},n.prototype.divideScalarX=function(t){return 0!==t?this.x/=t:this.x=0,this},n.prototype.divideScalarY=function(t){return 0!==t?this.y/=t:this.y=0,this},n.prototype.invertX=function(){return this.x*=-1,this},n.prototype.invertY=function(){return this.y*=-1,this},n.prototype.invert=function(){return this.invertX(),this.invertY(),this},n.prototype.multiplyX=function(t){return this.x*=t.x,this},n.prototype.multiplyY=function(t){return this.y*=t.y,this},n.prototype.multiply=function(t){return this.x*=t.x,this.y*=t.y,this},n.prototype.multiplyScalar=function(t){return this.x*=t,this.y*=t,this},n.prototype.multiplyScalarX=function(t){return this.x*=t,this},n.prototype.multiplyScalarY=function(t){return this.y*=t,this},n.prototype.normalize=function(){var t=this.length();return 0===t?(this.x=1,this.y=0):this.divide(n(t,t)),this},n.prototype.norm=n.prototype.normalize,n.prototype.limit=function(t,i){return Math.abs(this.x)>t&&(this.x*=i),Math.abs(this.y)>t&&(this.y*=i),this},n.prototype.randomize=function(t,i){return this.randomizeX(t,i),this.randomizeY(t,i),this},n.prototype.randomizeX=function(t,i){var r=Math.min(t.x,i.x),n=Math.max(t.x,i.x);return this.x=o(r,n),this},n.prototype.randomizeY=function(t,i){var r=Math.min(t.y,i.y),n=Math.max(t.y,i.y);return this.y=o(r,n),this},n.prototype.randomizeAny=function(t,i){return Math.round(Math.random())?this.randomizeX(t,i):this.randomizeY(t,i),this},n.prototype.unfloat=function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},n.prototype.toFixed=function(t){return"undefined"==typeof t&&(t=8),this.x=this.x.toFixed(t),this.y=this.y.toFixed(t),this},n.prototype.mixX=function(t,i){return"undefined"==typeof i&&(i=.5),this.x=(1-i)*this.x+i*t.x,this},n.prototype.mixY=function(t,i){return"undefined"==typeof i&&(i=.5),this.y=(1-i)*this.y+i*t.y,this},n.prototype.mix=function(t,i){return this.mixX(t,i),this.mixY(t,i),this},n.prototype.clone=function(){return new n(this.x,this.y)},n.prototype.copyX=function(t){return this.x=t.x,this},n.prototype.copyY=function(t){return this.y=t.y,this},n.prototype.copy=function(t){return this.copyX(t),this.copyY(t),this},n.prototype.zero=function(){return this.x=this.y=0,this},n.prototype.dot=function(t){return this.x*t.x+this.y*t.y},n.prototype.cross=function(t){return this.x*t.y-this.y*t.x},n.prototype.projectOnto=function(t){var i=(this.x*t.x+this.y*t.y)/(t.x*t.x+t.y*t.y);return this.x=i*t.x,this.y=i*t.y,this},n.prototype.horizontalAngle=function(){return Math.atan2(this.y,this.x)},n.prototype.horizontalAngleDeg=function(){return e(this.horizontalAngle())},n.prototype.verticalAngle=function(){return Math.atan2(this.x,this.y)},n.prototype.verticalAngleDeg=function(){return e(this.verticalAngle())},n.prototype.angle=n.prototype.horizontalAngle,n.prototype.angleDeg=n.prototype.horizontalAngleDeg,n.prototype.direction=n.prototype.horizontalAngle,n.prototype.rotate=function(t){var i=this.x*Math.cos(t)-this.y*Math.sin(t),r=this.x*Math.sin(t)+this.y*Math.cos(t);return this.x=i,this.y=r,this},n.prototype.rotateDeg=function(t){return t=s(t),this.rotate(t)},n.prototype.rotateTo=function(t){return this.rotate(t-this.angle())},n.prototype.rotateToDeg=function(t){return t=s(t),this.rotateTo(t)},n.prototype.rotateBy=function(t){var i=this.angle()+t;return this.rotate(i)},n.prototype.rotateByDeg=function(t){return t=s(t),this.rotateBy(t)},n.prototype.distanceX=function(t){return this.x-t.x},n.prototype.absDistanceX=function(t){return Math.abs(this.distanceX(t))},n.prototype.distanceY=function(t){return this.y-t.y},n.prototype.absDistanceY=function(t){return Math.abs(this.distanceY(t))},n.prototype.distance=function(t){return Math.sqrt(this.distanceSq(t))},n.prototype.distanceSq=function(t){var i=this.distanceX(t),r=this.distanceY(t);return i*i+r*r},n.prototype.length=function(){return Math.sqrt(this.lengthSq())},n.prototype.lengthSq=function(){return this.x*this.x+this.y*this.y},n.prototype.magnitude=n.prototype.length,n.prototype.isZero=function(){return 0===this.x&&0===this.y},n.prototype.isEqualTo=function(t){return this.x===t.x&&this.y===t.y},n.prototype.toString=function(){return"x:"+this.x+", y:"+this.y},n.prototype.toArray=function(){return[this.x,this.y]},n.prototype.toObject=function(){return{x:this.x,y:this.y}};var h=180/Math.PI},{}]},{},[1])(1)}); |