made with requirebin
Last active
January 12, 2017 09:55
-
-
Save kamicane/49567b290698badce686 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
another requirebin equation-designer early demo |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var ready = require("elements/domready"); | |
var get = function(one, two, three, four, t) { | |
var v = 1 - t, | |
b1 = t * t * t, | |
b2 = 3 * t * t * v, | |
b3 = 3 * t * v * v, | |
b4 = v * v * v; | |
return four * b1 + three * b2 + two * b3 + one * b4; | |
}; | |
var clamp = function(n, min, max) { | |
if (n < min) return min; | |
if (n > max) return max; | |
return n; | |
}; | |
var bezier = function(vectors, epsilon) { | |
if (vectors.length % 3 !== 1) throw new Error("invalid input"); | |
for (var i = 0; i < vectors.length - 1; i += 3) { | |
var c0 = vectors[i], | |
c1 = vectors[i + 1], | |
c2 = vectors[i + 2], | |
c3 = vectors[i + 3]; | |
if (i === 0) c0.x = 0; // clamp the first 0 to x 0 | |
else c0.x = clamp(c0.x, 0, 1); | |
if (i === vectors.length - 4) c3.x = 1; | |
else c3.x = clamp(c3.x, c0.x, 1); | |
// clamp the rest | |
c1.x = clamp(c1.x, c0.x, c3.x); | |
c2.x = clamp(c2.x, c0.x, c3.x); | |
} | |
return function(x) { | |
var c0, c1, c2, c3; | |
for (var i = 0; i < vectors.length - 1; i += 3) { | |
c0 = vectors[i]; | |
c1 = vectors[i + 1]; | |
c2 = vectors[i + 2]; | |
c3 = vectors[i + 3]; | |
if (x >= c0.x && x <= c3.x) break; | |
} | |
var lower = 0, upper = 1, t = x, xt; | |
if (x < lower) return get(c0.y, c1.y, c2.y, c3.y, lower); | |
if (x > upper) return get(c0.y, c1.y, c2.y, c3.y, upper); | |
while (lower < upper) { | |
xt = get(c0.x, c1.x, c2.x, c3.x, t); | |
if (Math.abs(xt - x) < epsilon) return get(c0.y, c1.y, c2.y, c3.y, t); | |
if (x > xt) lower = t; | |
else upper = t; | |
t = (upper - lower) * 0.5 + lower; | |
} | |
// Failure | |
return get(c0.y, c1.y, c2.y, c3.y, t); | |
}; | |
}; | |
var Transition = require("transition"); | |
var width = 900; | |
var height = 900; | |
var boxLeft = 100, | |
boxTop = 300; | |
var boxWidth = 600, | |
boxHeight = 300; | |
var convertVectorsToPixels = function(vectors) { | |
return vectors.map(function(v) { | |
return { x: boxLeft + (v.x * boxWidth), y: boxTop + ((-v.y + 1) * boxHeight) }; | |
}); | |
}; | |
// note: the cubic-bezier curve has its Y axis inverted | |
var convertVectorsToPercentages = function(vectors) { | |
return vectors.map(function(v) { | |
return { x: (v.x - boxLeft) / boxWidth, y: -((v.y - boxTop) / boxHeight) + 1 }; | |
}); | |
}; | |
var pixelVectors = convertVectorsToPixels([ | |
{ x: 0, y: 0 }, { x: 0, y: 1 }, { x: 0.5, y: 1 }, { x: 0.5, y: 0 }, | |
{ x: 0.5, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 0 } | |
]); | |
var lerp = function(from, to, delta) { | |
return (to - from) * delta + from; | |
}; | |
var equation; | |
var simplify = function(n, places) { | |
return Number(n).toFixed(places).replace(/\.?0+$/, ''); | |
}; | |
var render = function(ctx) { | |
var vectors = convertVectorsToPercentages(pixelVectors); | |
equation = bezier(vectors, 0.0001); // vectors are now clamped | |
pixelVectors = convertVectorsToPixels(vectors); // convert again for clamping | |
var i, c0, c1, c2, c3; | |
// clear canvas | |
ctx.clearRect(0, 0, width, height); | |
// draw main box | |
ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)'; | |
ctx.lineWidth = 1; | |
ctx.beginPath(); | |
ctx.rect(boxLeft, boxTop, boxWidth, boxHeight); | |
ctx.closePath(); | |
ctx.stroke(); | |
// draw bezier curves | |
ctx.strokeStyle = "red"; | |
c0 = pixelVectors[0]; | |
ctx.beginPath(); | |
ctx.moveTo(c0.x, c0.y); | |
for (i = 1; i < pixelVectors.length - 1; i += 3) { | |
c1 = pixelVectors[i]; | |
c2 = pixelVectors[i + 1]; | |
c3 = pixelVectors[i + 2]; | |
ctx.bezierCurveTo(c1.x, c1.y, c2.x, c2.y, c3.x, c3.y); | |
} | |
ctx.stroke(); | |
// draw control lines | |
ctx.strokeStyle = "green"; | |
for (i = 0; i < pixelVectors.length - 1; i += 3) { | |
c0 = pixelVectors[i]; | |
c1 = pixelVectors[i + 1]; | |
c2 = pixelVectors[i + 2]; | |
c3 = pixelVectors[i + 3]; | |
ctx.beginPath(); | |
ctx.moveTo(c0.x, c0.y); | |
ctx.lineTo(c1.x, c1.y); | |
ctx.closePath(); | |
ctx.stroke(); | |
ctx.beginPath(); | |
ctx.moveTo(c3.x, c3.y); | |
ctx.lineTo(c2.x, c2.y); | |
ctx.closePath(); | |
ctx.stroke(); | |
} | |
// draw control handles | |
for (i = 0; i < pixelVectors.length; i++) { | |
ctx.fillStyle = activePoint === i ? "cyan" : "green"; | |
var p = pixelVectors[i]; | |
ctx.beginPath(); | |
ctx.arc(p.x, p.y, 5 , 0, Math.PI * 2); | |
ctx.closePath(); | |
ctx.fill(); | |
} | |
document.querySelector("#curve").textContent = "cubicBezier([" + vectors.map(function(p) { | |
return "{ x: " + simplify(p.x, 2) + ", y: " + simplify(p.y, 2) + "}"; | |
}).join(", ") + "], 0.0001)"; | |
var res = 40; | |
var points = []; | |
for (i = 0; i < res; i++) { | |
var pct = i / (res - 1); | |
var x = boxLeft + (pct * boxWidth); | |
var line = [{ x: x, y: boxTop + boxHeight }, { x: x, y: boxTop }]; | |
ctx.strokeStyle = "rgba(255, 255, 255, 0.05)"; | |
ctx.beginPath(); | |
ctx.moveTo(line[0].x, line[0].y); | |
ctx.lineTo(line[1].x, line[1].y); | |
ctx.closePath(); | |
ctx.stroke(); | |
var y = boxTop + ((-equation(pct) + 1) * boxHeight); | |
points.push({ x: x, y: y }); | |
} | |
// draw computed points | |
ctx.fillStyle = "blue"; | |
points.forEach(function(p) { | |
ctx.beginPath(); | |
ctx.arc(p.x, p.y, 2, 0, Math.PI * 2); | |
ctx.closePath(); | |
ctx.fill(); | |
}); | |
}; | |
var activePoint; | |
var contained = function(p, box) { | |
return p.x >= box.left && p.x <= box.right && p.y >= box.top && p.y <= box.bottom; | |
}; | |
var findCurvePoint = function(p) { | |
var found; | |
for (var i = 0; i < pixelVectors.length; i++) { | |
var cp = pixelVectors[i]; | |
var box = { left: cp.x - 10, right: cp.x + 10, top: cp.y - 10, bottom: cp.y + 10 }; | |
if (contained(p, box)) { | |
found = i; | |
break; | |
} | |
} | |
activePoint = found; | |
}; | |
ready(function() { | |
var canvas = document.querySelector("#curves"); | |
canvas.width = width; | |
canvas.height = height; | |
var ctx = canvas.getContext("2d"); | |
render(ctx); | |
document.addEventListener("mousedown", function(event) { | |
findCurvePoint({ x: event.pageX, y: event.pageY }); | |
if (activePoint != null) render(ctx); | |
}, false); | |
document.addEventListener("mouseup", function() { | |
if (activePoint != null) { | |
activePoint = null; | |
render(ctx); | |
} | |
}, false); | |
document.addEventListener("mousemove", function(event) { | |
if (activePoint == null) return; | |
pixelVectors[activePoint] = { x: event.pageX, y: event.pageY }; | |
event.preventDefault(); | |
render(ctx); | |
}, false); | |
document.querySelector("#add").addEventListener("click", function() { | |
var vectors = convertVectorsToPercentages(pixelVectors); | |
var segments = (vectors.length - 1) / 3 + 1; | |
var ratio = 1 - (1 / segments); | |
for (var i = 0; i < vectors.length; i++) { | |
var c = vectors[i]; | |
c.x *= ratio; | |
} | |
vectors.push({ x: ratio, y: 1 }, { x: 1, y: 1 }, {x: 1, y: 0 }); | |
pixelVectors = convertVectorsToPixels(vectors); | |
render(ctx); | |
}, false); | |
var sprite = document.querySelector("#sprite"); | |
document.querySelector("#fade-in").addEventListener("click", function() { | |
var start = 0, end = 1; | |
var transition = new Transition(5000, equation, function(delta) { | |
sprite.style.opacity = lerp(start, end, delta); | |
}); | |
transition.start(); | |
}, false); | |
document.querySelector("#fade-out").addEventListener("click", function() { | |
var start = 1, end = 0; | |
var transition = new Transition(5000, equation, function(delta) { | |
sprite.style.opacity = lerp(start, end, delta); | |
}); | |
transition.start(); | |
}, false); | |
document.querySelector("#rise").addEventListener("click", function() { | |
var start = 800, end = 100; | |
sprite.style.opacity = 1; | |
var transition = new Transition(5000, equation, function(delta) { | |
sprite.style.top = lerp(start, end, delta) + "px"; | |
}); | |
transition.start(); | |
}, false); | |
document.querySelector("#fall").addEventListener("click", function() { | |
var start = 100, end = 800; | |
sprite.style.opacity = 1; | |
var transition = new Transition(5000, equation, function(delta) { | |
sprite.style.top = lerp(start, end, delta) + "px"; | |
}); | |
transition.start(); | |
}, false); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var process=module.exports={};process.nextTick=function(){var canSetImmediate=typeof window!=="undefined"&&window.setImmediate;var canMutationObserver=typeof window!=="undefined"&&window.MutationObserver;var canPost=typeof window!=="undefined"&&window.postMessage&&window.addEventListener;if(canSetImmediate){return function(f){return window.setImmediate(f)}}var queue=[];if(canMutationObserver){var hiddenDiv=document.createElement("div");var observer=new MutationObserver(function(){var queueList=queue.slice();queue.length=0;queueList.forEach(function(fn){fn()})});observer.observe(hiddenDiv,{attributes:true});return function nextTick(fn){if(!queue.length){hiddenDiv.setAttribute("yes","no")}queue.push(fn)}}if(canPost){window.addEventListener("message",function(ev){var source=ev.source;if((source===window||source===null)&&ev.data==="process-tick"){ev.stopPropagation();if(queue.length>0){var fn=queue.shift();fn()}}},true);return function nextTick(fn){queue.push(fn);window.postMessage("process-tick","*")}}return function nextTick(fn){setTimeout(fn,0)}}();process.title="browser";process.browser=true;process.env={};process.argv=[];function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")}},{}],2:[function(require,module,exports){"use strict";var prime=require("prime"),defer=require("prime/defer");var Transition=prime({constructor:function Transition(duration,equation,callback){if(!duration)throw new Error("no duration given");if(!equation)throw new Error("no equation given");if(!callback)throw new Error("no callback given");this.duration=duration;this.equation=equation;this.callback=callback},get paused(){return this.cancel==null&&this.elapsed!=null},get active(){return this.cancel!=null},get idle(){return this.cancel==null&&this.elapsed==null},start:function(){if(this.idle){this.elapsed=0;this.cancel=defer.frame(this.step,this)}return this},step:function(time){this.elapsed+=time-(this.time||time);var factor=this.elapsed/this.duration;if(factor>1)factor=1;if(factor!==1){this.time=time;this.cancel=defer.frame(this.step,this)}else{this.cancel=this.time=this.elapsed=null}var delta=this.equation(factor);this.callback(delta)},stop:function(){if(this.active){this.cancel();this.elapsed=this.cancel=this.time=null}return this},pause:function(){if(this.active){this.cancel();this.cancel=this.time=null}return this},resume:function(){if(this.paused){this.cancel=defer.frame(this.step,this)}return this}});module.exports=Transition},{prime:13,"prime/defer":12}],3:[function(require,module,exports){function forEach(arr,callback,thisObj){if(arr==null){return}var i=-1,len=arr.length;while(++i<len){if(callback.call(thisObj,arr[i],i,arr)===false){break}}}module.exports=forEach},{}],4:[function(require,module,exports){function indexOf(arr,item,fromIndex){fromIndex=fromIndex||0;if(arr==null){return-1}var len=arr.length,i=fromIndex<0?len+fromIndex:fromIndex;while(i<len){if(arr[i]===item){return i}i++}return-1}module.exports=indexOf},{}],5:[function(require,module,exports){var mixIn=require("../object/mixIn");function createObject(parent,props){function F(){}F.prototype=parent;return mixIn(new F,props)}module.exports=createObject},{"../object/mixIn":10}],6:[function(require,module,exports){var _rKind=/^\[object (.*)\]$/,_toString=Object.prototype.toString,UNDEF;function kindOf(val){if(val===null){return"Null"}else if(val===UNDEF){return"Undefined"}else{return _rKind.exec(_toString.call(val))[1]}}module.exports=kindOf},{}],7:[function(require,module,exports){var hasOwn=require("./hasOwn");var _hasDontEnumBug,_dontEnums;function checkDontEnum(){_dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];_hasDontEnumBug=true;for(var key in{toString:null}){_hasDontEnumBug=false}}function forIn(obj,fn,thisObj){var key,i=0;if(_hasDontEnumBug==null)checkDontEnum();for(key in obj){if(exec(fn,obj,key,thisObj)===false){break}}if(_hasDontEnumBug){var ctor=obj.constructor,isProto=!!ctor&&obj===ctor.prototype;while(key=_dontEnums[i++]){if((key!=="constructor"||!isProto&&hasOwn(obj,key))&&obj[key]!==Object.prototype[key]){if(exec(fn,obj,key,thisObj)===false){break}}}}}function exec(fn,obj,key,thisObj){return fn.call(thisObj,obj[key],key,obj)}module.exports=forIn},{"./hasOwn":9}],8:[function(require,module,exports){var hasOwn=require("./hasOwn");var forIn=require("./forIn");function forOwn(obj,fn,thisObj){forIn(obj,function(val,key){if(hasOwn(obj,key)){return fn.call(thisObj,obj[key],key,obj)}})}module.exports=forOwn},{"./forIn":7,"./hasOwn":9}],9:[function(require,module,exports){function hasOwn(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}module.exports=hasOwn},{}],10:[function(require,module,exports){var forOwn=require("./forOwn");function mixIn(target,objects){var i=0,n=arguments.length,obj;while(++i<n){obj=arguments[i];if(obj!=null){forOwn(obj,copyProp,target)}}return target}function copyProp(val,key){this[key]=val}module.exports=mixIn},{"./forOwn":8}],11:[function(require,module,exports){function now(){return now.get()}now.get=typeof Date.now==="function"?Date.now:function(){return+new Date};module.exports=now},{}],12:[function(require,module,exports){(function(process,global){"use strict";var kindOf=require("mout/lang/kindOf"),now=require("mout/time/now"),forEach=require("mout/array/forEach"),indexOf=require("mout/array/indexOf");var callbacks={timeout:{},frame:[],immediate:[]};var push=function(collection,callback,context,defer){var iterator=function(){iterate(collection)};if(!collection.length)defer(iterator);var entry={callback:callback,context:context};collection.push(entry);return function(){var io=indexOf(collection,entry);if(io>-1)collection.splice(io,1)}};var iterate=function(collection){var time=now();forEach(collection.splice(0),function(entry){entry.callback.call(entry.context,time)})};var defer=function(callback,argument,context){return kindOf(argument)==="Number"?defer.timeout(callback,argument,context):defer.immediate(callback,argument)};if(global.process&&process.nextTick){defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,process.nextTick)}}else if(global.setImmediate){defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,setImmediate)}}else if(global.postMessage&&global.addEventListener){addEventListener("message",function(event){if(event.source===global&&event.data==="@deferred"){event.stopPropagation();iterate(callbacks.immediate)}},true);defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,function(){postMessage("@deferred","*")})}}else{defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,function(iterator){setTimeout(iterator,0)})}}var requestAnimationFrame=global.requestAnimationFrame||global.webkitRequestAnimationFrame||global.mozRequestAnimationFrame||global.oRequestAnimationFrame||global.msRequestAnimationFrame||function(callback){setTimeout(callback,1e3/60)};defer.frame=function(callback,context){return push(callbacks.frame,callback,context,requestAnimationFrame)};var clear;defer.timeout=function(callback,ms,context){var ct=callbacks.timeout;if(!clear)clear=defer.immediate(function(){clear=null;callbacks.timeout={}});return push(ct[ms]||(ct[ms]=[]),callback,context,function(iterator){setTimeout(iterator,ms)})};module.exports=defer}).call(this,require("_process"),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{_process:1,"mout/array/forEach":3,"mout/array/indexOf":4,"mout/lang/kindOf":6,"mout/time/now":11}],13:[function(require,module,exports){"use strict";var hasOwn=require("mout/object/hasOwn"),mixIn=require("mout/object/mixIn"),create=require("mout/lang/createObject"),kindOf=require("mout/lang/kindOf");var hasDescriptors=true;try{Object.defineProperty({},"~",{});Object.getOwnPropertyDescriptor({},"~")}catch(e){hasDescriptors=false}var hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),buggy=["toString","valueOf"];var verbs=/^constructor|inherits|mixin$/;var implement=function(proto){var prototype=this.prototype;for(var key in proto){if(key.match(verbs))continue;if(hasDescriptors){var descriptor=Object.getOwnPropertyDescriptor(proto,key);if(descriptor){Object.defineProperty(prototype,key,descriptor);continue}}prototype[key]=proto[key]}if(hasEnumBug)for(var i=0;key=buggy[i];i++){var value=proto[key];if(value!==Object.prototype[key])prototype[key]=value}return this};var prime=function(proto){if(kindOf(proto)==="Function")proto={constructor:proto};var superprime=proto.inherits;var constructor=hasOwn(proto,"constructor")?proto.constructor:superprime?function(){return superprime.apply(this,arguments)}:function(){};if(superprime){mixIn(constructor,superprime);var superproto=superprime.prototype;var cproto=constructor.prototype=create(superproto);constructor.parent=superproto;cproto.constructor=constructor}if(!constructor.implement)constructor.implement=implement;var mixins=proto.mixin;if(mixins){if(kindOf(mixins)!=="Array")mixins=[mixins];for(var i=0;i<mixins.length;i++)constructor.implement(create(mixins[i].prototype))}return constructor.implement(proto)};module.exports=prime},{"mout/lang/createObject":5,"mout/lang/kindOf":6,"mout/object/hasOwn":9,"mout/object/mixIn":10}],transition:[function(require,module,exports){"use strict";module.exports=require("./lib/transition")},{"./lib/transition":2}]},{},[]);require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var process=module.exports={};process.nextTick=function(){var canSetImmediate=typeof window!=="undefined"&&window.setImmediate;var canMutationObserver=typeof window!=="undefined"&&window.MutationObserver;var canPost=typeof window!=="undefined"&&window.postMessage&&window.addEventListener;if(canSetImmediate){return function(f){return window.setImmediate(f)}}var queue=[];if(canMutationObserver){var hiddenDiv=document.createElement("div");var observer=new MutationObserver(function(){var queueList=queue.slice();queue.length=0;queueList.forEach(function(fn){fn()})});observer.observe(hiddenDiv,{attributes:true});return function nextTick(fn){if(!queue.length){hiddenDiv.setAttribute("yes","no")}queue.push(fn)}}if(canPost){window.addEventListener("message",function(ev){var source=ev.source;if((source===window||source===null)&&ev.data==="process-tick"){ev.stopPropagation();if(queue.length>0){var fn=queue.shift();fn()}}},true);return function nextTick(fn){queue.push(fn);window.postMessage("process-tick","*")}}return function nextTick(fn){setTimeout(fn,0)}}();process.title="browser";process.browser=true;process.env={};process.argv=[];function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")}},{}],2:[function(require,module,exports){"use strict";var prime=require("prime");var forEach=require("mout/array/forEach"),map=require("mout/array/map"),filter=require("mout/array/filter"),every=require("mout/array/every"),some=require("mout/array/some");var index=0,__dc=document.__counter,counter=document.__counter=(__dc?parseInt(__dc,36)+1:0).toString(36),key="uid:"+counter;var uniqueID=function(n){if(n===window)return"window";if(n===document)return"document";if(n===document.documentElement)return"html";return n[key]||(n[key]=(index++).toString(36))};var instances={};var $=prime({constructor:function $(n,context){if(n==null)return this&&this.constructor===$?new Elements:null;var self,uid;if(n.constructor!==Elements){self=new Elements;if(typeof n==="string"){if(!self.search)return null;self[self.length++]=context||document;return self.search(n)}if(n.nodeType||n===window){self[self.length++]=n}else if(n.length){var uniques={};for(var i=0,l=n.length;i<l;i++){var nodes=$(n[i],context);if(nodes&&nodes.length)for(var j=0,k=nodes.length;j<k;j++){var node=nodes[j];uid=uniqueID(node);if(!uniques[uid]){self[self.length++]=node;uniques[uid]=true}}}}}else{self=n}if(!self.length)return null;if(self.length===1){uid=uniqueID(self[0]);return instances[uid]||(instances[uid]=self)}return self}});var Elements=prime({inherits:$,constructor:function Elements(){this.length=0},unlink:function(){return this.map(function(node){delete instances[uniqueID(node)];return node})},forEach:function(method,context){forEach(this,method,context);return this},map:function(method,context){return map(this,method,context)},filter:function(method,context){return filter(this,method,context)},every:function(method,context){return every(this,method,context)},some:function(method,context){return some(this,method,context)}});module.exports=$},{"mout/array/every":4,"mout/array/filter":5,"mout/array/forEach":6,"mout/array/map":8,"mout/array/some":9,prime:25}],3:[function(require,module,exports){"use strict";var Emitter=require("prime/emitter");var $=require("./base");var html=document.documentElement;var addEventListener=html.addEventListener?function(node,event,handle,useCapture){node.addEventListener(event,handle,useCapture||false);return handle}:function(node,event,handle){node.attachEvent("on"+event,handle);return handle};var removeEventListener=html.removeEventListener?function(node,event,handle,useCapture){node.removeEventListener(event,handle,useCapture||false)}:function(node,event,handle){node.detachEvent("on"+event,handle)};$.implement({on:function(event,handle,useCapture){return this.forEach(function(node){var self=$(node);var internalEvent=event+(useCapture?":capture":"");Emitter.prototype.on.call(self,internalEvent,handle);var domListeners=self._domListeners||(self._domListeners={});if(!domListeners[internalEvent])domListeners[internalEvent]=addEventListener(node,event,function(e){Emitter.prototype.emit.call(self,internalEvent,e||window.event,Emitter.EMIT_SYNC)},useCapture)})},off:function(event,handle,useCapture){return this.forEach(function(node){var self=$(node);var internalEvent=event+(useCapture?":capture":"");var domListeners=self._domListeners,domEvent,listeners=self._listeners,events;if(domListeners&&(domEvent=domListeners[internalEvent])&&listeners&&(events=listeners[internalEvent])){Emitter.prototype.off.call(self,internalEvent,handle);if(!self._listeners||!self._listeners[event]){removeEventListener(node,event,domEvent);delete domListeners[event];for(var l in domListeners)return;delete self._domListeners}}})},emit:function(){var args=arguments;return this.forEach(function(node){Emitter.prototype.emit.apply($(node),args)})}});module.exports=$},{"./base":2,"prime/emitter":24}],4:[function(require,module,exports){var makeIterator=require("../function/makeIterator_");function every(arr,callback,thisObj){callback=makeIterator(callback,thisObj);var result=true;if(arr==null){return result}var i=-1,len=arr.length;while(++i<len){if(!callback(arr[i],i,arr)){result=false;break}}return result}module.exports=every},{"../function/makeIterator_":11}],5:[function(require,module,exports){var makeIterator=require("../function/makeIterator_");function filter(arr,callback,thisObj){callback=makeIterator(callback,thisObj);var results=[];if(arr==null){return results}var i=-1,len=arr.length,value;while(++i<len){value=arr[i];if(callback(value,i,arr)){results.push(value)}}return results}module.exports=filter},{"../function/makeIterator_":11}],6:[function(require,module,exports){function forEach(arr,callback,thisObj){if(arr==null){return}var i=-1,len=arr.length;while(++i<len){if(callback.call(thisObj,arr[i],i,arr)===false){break}}}module.exports=forEach},{}],7:[function(require,module,exports){function indexOf(arr,item,fromIndex){fromIndex=fromIndex||0;if(arr==null){return-1}var len=arr.length,i=fromIndex<0?len+fromIndex:fromIndex;while(i<len){if(arr[i]===item){return i}i++}return-1}module.exports=indexOf},{}],8:[function(require,module,exports){var makeIterator=require("../function/makeIterator_");function map(arr,callback,thisObj){callback=makeIterator(callback,thisObj);var results=[];if(arr==null){return results}var i=-1,len=arr.length;while(++i<len){results[i]=callback(arr[i],i,arr)}return results}module.exports=map},{"../function/makeIterator_":11}],9:[function(require,module,exports){var makeIterator=require("../function/makeIterator_");function some(arr,callback,thisObj){callback=makeIterator(callback,thisObj);var result=false;if(arr==null){return result}var i=-1,len=arr.length;while(++i<len){if(callback(arr[i],i,arr)){result=true;break}}return result}module.exports=some},{"../function/makeIterator_":11}],10:[function(require,module,exports){function identity(val){return val}module.exports=identity},{}],11:[function(require,module,exports){var identity=require("./identity");var prop=require("./prop");var deepMatches=require("../object/deepMatches");function makeIterator(src,thisObj){if(src==null){return identity}switch(typeof src){case"function":return typeof thisObj!=="undefined"?function(val,i,arr){return src.call(thisObj,val,i,arr)}:src;case"object":return function(val){return deepMatches(val,src)};case"string":case"number":return prop(src)}}module.exports=makeIterator},{"../object/deepMatches":17,"./identity":10,"./prop":12}],12:[function(require,module,exports){function prop(name){return function(obj){return obj[name]}}module.exports=prop},{}],13:[function(require,module,exports){var mixIn=require("../object/mixIn");function createObject(parent,props){function F(){}F.prototype=parent;return mixIn(new F,props)}module.exports=createObject},{"../object/mixIn":21}],14:[function(require,module,exports){var isKind=require("./isKind");var isArray=Array.isArray||function(val){return isKind(val,"Array")};module.exports=isArray},{"./isKind":15}],15:[function(require,module,exports){var kindOf=require("./kindOf");function isKind(val,kind){return kindOf(val)===kind}module.exports=isKind},{"./kindOf":16}],16:[function(require,module,exports){var _rKind=/^\[object (.*)\]$/,_toString=Object.prototype.toString,UNDEF;function kindOf(val){if(val===null){return"Null"}else if(val===UNDEF){return"Undefined"}else{return _rKind.exec(_toString.call(val))[1]}}module.exports=kindOf},{}],17:[function(require,module,exports){var forOwn=require("./forOwn");var isArray=require("../lang/isArray");function containsMatch(array,pattern){var i=-1,length=array.length;while(++i<length){if(deepMatches(array[i],pattern)){return true}}return false}function matchArray(target,pattern){var i=-1,patternLength=pattern.length;while(++i<patternLength){if(!containsMatch(target,pattern[i])){return false}}return true}function matchObject(target,pattern){var result=true;forOwn(pattern,function(val,key){if(!deepMatches(target[key],val)){return result=false}});return result}function deepMatches(target,pattern){if(target&&typeof target==="object"){if(isArray(target)&&isArray(pattern)){return matchArray(target,pattern)}else{return matchObject(target,pattern)}}else{return target===pattern}}module.exports=deepMatches},{"../lang/isArray":14,"./forOwn":19}],18:[function(require,module,exports){var hasOwn=require("./hasOwn");var _hasDontEnumBug,_dontEnums;function checkDontEnum(){_dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];_hasDontEnumBug=true;for(var key in{toString:null}){_hasDontEnumBug=false}}function forIn(obj,fn,thisObj){var key,i=0;if(_hasDontEnumBug==null)checkDontEnum();for(key in obj){if(exec(fn,obj,key,thisObj)===false){break}}if(_hasDontEnumBug){var ctor=obj.constructor,isProto=!!ctor&&obj===ctor.prototype;while(key=_dontEnums[i++]){if((key!=="constructor"||!isProto&&hasOwn(obj,key))&&obj[key]!==Object.prototype[key]){if(exec(fn,obj,key,thisObj)===false){break}}}}}function exec(fn,obj,key,thisObj){return fn.call(thisObj,obj[key],key,obj)}module.exports=forIn},{"./hasOwn":20}],19:[function(require,module,exports){var hasOwn=require("./hasOwn");var forIn=require("./forIn");function forOwn(obj,fn,thisObj){forIn(obj,function(val,key){if(hasOwn(obj,key)){return fn.call(thisObj,obj[key],key,obj)}})}module.exports=forOwn},{"./forIn":18,"./hasOwn":20}],20:[function(require,module,exports){function hasOwn(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}module.exports=hasOwn},{}],21:[function(require,module,exports){var forOwn=require("./forOwn");function mixIn(target,objects){var i=0,n=arguments.length,obj;while(++i<n){obj=arguments[i];if(obj!=null){forOwn(obj,copyProp,target)}}return target}function copyProp(val,key){this[key]=val}module.exports=mixIn},{"./forOwn":19}],22:[function(require,module,exports){function now(){return now.get()}now.get=typeof Date.now==="function"?Date.now:function(){return+new Date};module.exports=now},{}],23:[function(require,module,exports){(function(process,global){"use strict";var kindOf=require("mout/lang/kindOf"),now=require("mout/time/now"),forEach=require("mout/array/forEach"),indexOf=require("mout/array/indexOf");var callbacks={timeout:{},frame:[],immediate:[]};var push=function(collection,callback,context,defer){var iterator=function(){iterate(collection)};if(!collection.length)defer(iterator);var entry={callback:callback,context:context};collection.push(entry);return function(){var io=indexOf(collection,entry);if(io>-1)collection.splice(io,1)}};var iterate=function(collection){var time=now();forEach(collection.splice(0),function(entry){entry.callback.call(entry.context,time)})};var defer=function(callback,argument,context){return kindOf(argument)==="Number"?defer.timeout(callback,argument,context):defer.immediate(callback,argument)};if(global.process&&process.nextTick){defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,process.nextTick)}}else if(global.setImmediate){defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,setImmediate)}}else if(global.postMessage&&global.addEventListener){addEventListener("message",function(event){if(event.source===global&&event.data==="@deferred"){event.stopPropagation();iterate(callbacks.immediate)}},true);defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,function(){postMessage("@deferred","*")})}}else{defer.immediate=function(callback,context){return push(callbacks.immediate,callback,context,function(iterator){setTimeout(iterator,0)})}}var requestAnimationFrame=global.requestAnimationFrame||global.webkitRequestAnimationFrame||global.mozRequestAnimationFrame||global.oRequestAnimationFrame||global.msRequestAnimationFrame||function(callback){setTimeout(callback,1e3/60)};defer.frame=function(callback,context){return push(callbacks.frame,callback,context,requestAnimationFrame)};var clear;defer.timeout=function(callback,ms,context){var ct=callbacks.timeout;if(!clear)clear=defer.immediate(function(){clear=null;callbacks.timeout={}});return push(ct[ms]||(ct[ms]=[]),callback,context,function(iterator){setTimeout(iterator,ms)})};module.exports=defer}).call(this,require("_process"),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{_process:1,"mout/array/forEach":6,"mout/array/indexOf":7,"mout/lang/kindOf":16,"mout/time/now":22}],24:[function(require,module,exports){"use strict";var indexOf=require("mout/array/indexOf"),forEach=require("mout/array/forEach");var prime=require("./index"),defer=require("./defer");var slice=Array.prototype.slice;var Emitter=prime({on:function(event,fn){var listeners=this._listeners||(this._listeners={}),events=listeners[event]||(listeners[event]=[]);if(indexOf(events,fn)===-1)events.push(fn);return this},off:function(event,fn){var listeners=this._listeners,events,key,length=0;if(listeners&&(events=listeners[event])){var io=indexOf(events,fn);if(io>-1)events.splice(io,1);if(!events.length)delete listeners[event];for(var l in listeners)return this;delete this._listeners}return this},emit:function(event){var self=this,args=slice.call(arguments,1);var emit=function(){var listeners=self._listeners,events;if(listeners&&(events=listeners[event])){forEach(events.slice(0),function(event){return event.apply(self,args)})}};if(args[args.length-1]===Emitter.EMIT_SYNC){args.pop();emit()}else{defer(emit)}return this}});Emitter.EMIT_SYNC={};module.exports=Emitter},{"./defer":23,"./index":25,"mout/array/forEach":6,"mout/array/indexOf":7}],25:[function(require,module,exports){"use strict";var hasOwn=require("mout/object/hasOwn"),mixIn=require("mout/object/mixIn"),create=require("mout/lang/createObject"),kindOf=require("mout/lang/kindOf");var hasDescriptors=true;try{Object.defineProperty({},"~",{});Object.getOwnPropertyDescriptor({},"~")}catch(e){hasDescriptors=false}var hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),buggy=["toString","valueOf"];var verbs=/^constructor|inherits|mixin$/;var implement=function(proto){var prototype=this.prototype;for(var key in proto){if(key.match(verbs))continue;if(hasDescriptors){var descriptor=Object.getOwnPropertyDescriptor(proto,key);if(descriptor){Object.defineProperty(prototype,key,descriptor);continue}}prototype[key]=proto[key]}if(hasEnumBug)for(var i=0;key=buggy[i];i++){var value=proto[key];if(value!==Object.prototype[key])prototype[key]=value}return this};var prime=function(proto){if(kindOf(proto)==="Function")proto={constructor:proto};var superprime=proto.inherits;var constructor=hasOwn(proto,"constructor")?proto.constructor:superprime?function(){return superprime.apply(this,arguments)}:function(){};if(superprime){mixIn(constructor,superprime);var superproto=superprime.prototype;var cproto=constructor.prototype=create(superproto);constructor.parent=superproto;cproto.constructor=constructor}if(!constructor.implement)constructor.implement=implement;var mixins=proto.mixin;if(mixins){if(kindOf(mixins)!=="Array")mixins=[mixins];for(var i=0;i<mixins.length;i++)constructor.implement(create(mixins[i].prototype))}return constructor.implement(proto)};module.exports=prime},{"mout/lang/createObject":13,"mout/lang/kindOf":16,"mout/object/hasOwn":20,"mout/object/mixIn":21}],"elements/domready":[function(require,module,exports){"use strict";var $=require("./events");var readystatechange="onreadystatechange"in document,shouldPoll=false,loaded=false,readys=[],checks=[],ready=null,timer=null,test=document.createElement("div"),doc=$(document),win=$(window);var domready=function(){if(timer)timer=clearTimeout(timer);if(!loaded){if(readystatechange)doc.off("readystatechange",check);doc.off("DOMContentLoaded",domready);win.off("load",domready);loaded=true;for(var i=0;ready=readys[i++];)ready()}return loaded};var check=function(){for(var i=checks.length;i--;)if(checks[i]())return domready();return false};var poll=function(){clearTimeout(timer);if(!check())timer=setTimeout(poll,1e3/60)};if(document.readyState){var complete=function(){return!!/loaded|complete/.test(document.readyState)};checks.push(complete);if(!complete()){if(readystatechange)doc.on("readystatechange",check);else shouldPoll=true}else{domready()}}if(test.doScroll){var scrolls=function(){try{test.doScroll();return true}catch(e){}return false};if(!scrolls()){checks.push(scrolls);shouldPoll=true}}if(shouldPoll)poll();doc.on("DOMContentLoaded",domready);win.on("load",domready);module.exports=function(ready){loaded?ready():readys.push(ready);return null}},{"./events":3}]},{},[]);"use strict";var ready=require("elements/domready");var get=function(one,two,three,four,t){var v=1-t,b1=t*t*t,b2=3*t*t*v,b3=3*t*v*v,b4=v*v*v;return four*b1+three*b2+two*b3+one*b4};var clamp=function(n,min,max){if(n<min)return min;if(n>max)return max;return n};var bezier=function(vectors,epsilon){if(vectors.length%3!==1)throw new Error("invalid input");for(var i=0;i<vectors.length-1;i+=3){var c0=vectors[i],c1=vectors[i+1],c2=vectors[i+2],c3=vectors[i+3];if(i===0)c0.x=0;else c0.x=clamp(c0.x,0,1);if(i===vectors.length-4)c3.x=1;else c3.x=clamp(c3.x,c0.x,1);c1.x=clamp(c1.x,c0.x,c3.x);c2.x=clamp(c2.x,c0.x,c3.x)}return function(x){var c0,c1,c2,c3;for(var i=0;i<vectors.length-1;i+=3){c0=vectors[i];c1=vectors[i+1];c2=vectors[i+2];c3=vectors[i+3];if(x>=c0.x&&x<=c3.x)break}var lower=0,upper=1,t=x,xt;if(x<lower)return get(c0.y,c1.y,c2.y,c3.y,lower);if(x>upper)return get(c0.y,c1.y,c2.y,c3.y,upper);while(lower<upper){xt=get(c0.x,c1.x,c2.x,c3.x,t);if(Math.abs(xt-x)<epsilon)return get(c0.y,c1.y,c2.y,c3.y,t);if(x>xt)lower=t;else upper=t;t=(upper-lower)*.5+lower}return get(c0.y,c1.y,c2.y,c3.y,t)}};var Transition=require("transition");var width=900;var height=900;var boxLeft=100,boxTop=300;var boxWidth=600,boxHeight=300;var convertVectorsToPixels=function(vectors){return vectors.map(function(v){return{x:boxLeft+v.x*boxWidth,y:boxTop+(-v.y+1)*boxHeight}})};var convertVectorsToPercentages=function(vectors){return vectors.map(function(v){return{x:(v.x-boxLeft)/boxWidth,y:-((v.y-boxTop)/boxHeight)+1}})};var pixelVectors=convertVectorsToPixels([{x:0,y:0},{x:0,y:1},{x:.5,y:1},{x:.5,y:0},{x:.5,y:1},{x:1,y:1},{x:1,y:0}]);var lerp=function(from,to,delta){return(to-from)*delta+from};var equation;var simplify=function(n,places){return Number(n).toFixed(places).replace(/\.?0+$/,"")};var render=function(ctx){var vectors=convertVectorsToPercentages(pixelVectors);equation=bezier(vectors,1e-4);pixelVectors=convertVectorsToPixels(vectors);var i,c0,c1,c2,c3;ctx.clearRect(0,0,width,height);ctx.strokeStyle="rgba(255, 255, 255, 0.2)";ctx.lineWidth=1;ctx.beginPath();ctx.rect(boxLeft,boxTop,boxWidth,boxHeight);ctx.closePath();ctx.stroke();ctx.strokeStyle="red";c0=pixelVectors[0];ctx.beginPath();ctx.moveTo(c0.x,c0.y);for(i=1;i<pixelVectors.length-1;i+=3){c1=pixelVectors[i];c2=pixelVectors[i+1];c3=pixelVectors[i+2];ctx.bezierCurveTo(c1.x,c1.y,c2.x,c2.y,c3.x,c3.y)}ctx.stroke();ctx.strokeStyle="green";for(i=0;i<pixelVectors.length-1;i+=3){c0=pixelVectors[i];c1=pixelVectors[i+1];c2=pixelVectors[i+2];c3=pixelVectors[i+3];ctx.beginPath();ctx.moveTo(c0.x,c0.y);ctx.lineTo(c1.x,c1.y);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(c3.x,c3.y);ctx.lineTo(c2.x,c2.y);ctx.closePath();ctx.stroke()}for(i=0;i<pixelVectors.length;i++){ctx.fillStyle=activePoint===i?"cyan":"green";var p=pixelVectors[i];ctx.beginPath();ctx.arc(p.x,p.y,5,0,Math.PI*2);ctx.closePath();ctx.fill()}document.querySelector("#curve").textContent="cubicBezier(["+vectors.map(function(p){return"{ x: "+simplify(p.x,2)+", y: "+simplify(p.y,2)+"}"}).join(", ")+"], 0.0001)";var res=40;var points=[];for(i=0;i<res;i++){var pct=i/(res-1);var x=boxLeft+pct*boxWidth;var line=[{x:x,y:boxTop+boxHeight},{x:x,y:boxTop}];ctx.strokeStyle="rgba(255, 255, 255, 0.05)";ctx.beginPath();ctx.moveTo(line[0].x,line[0].y);ctx.lineTo(line[1].x,line[1].y);ctx.closePath();ctx.stroke(); | |
var y=boxTop+(-equation(pct)+1)*boxHeight;points.push({x:x,y:y})}ctx.fillStyle="blue";points.forEach(function(p){ctx.beginPath();ctx.arc(p.x,p.y,2,0,Math.PI*2);ctx.closePath();ctx.fill()})};var activePoint;var contained=function(p,box){return p.x>=box.left&&p.x<=box.right&&p.y>=box.top&&p.y<=box.bottom};var findCurvePoint=function(p){var found;for(var i=0;i<pixelVectors.length;i++){var cp=pixelVectors[i];var box={left:cp.x-10,right:cp.x+10,top:cp.y-10,bottom:cp.y+10};if(contained(p,box)){found=i;break}}activePoint=found};ready(function(){var canvas=document.querySelector("#curves");canvas.width=width;canvas.height=height;var ctx=canvas.getContext("2d");render(ctx);document.addEventListener("mousedown",function(event){findCurvePoint({x:event.pageX,y:event.pageY});if(activePoint!=null)render(ctx)},false);document.addEventListener("mouseup",function(){if(activePoint!=null){activePoint=null;render(ctx)}},false);document.addEventListener("mousemove",function(event){if(activePoint==null)return;pixelVectors[activePoint]={x:event.pageX,y:event.pageY};event.preventDefault();render(ctx)},false);document.querySelector("#add").addEventListener("click",function(){var vectors=convertVectorsToPercentages(pixelVectors);var segments=(vectors.length-1)/3+1;var ratio=1-1/segments;for(var i=0;i<vectors.length;i++){var c=vectors[i];c.x*=ratio}vectors.push({x:ratio,y:1},{x:1,y:1},{x:1,y:0});pixelVectors=convertVectorsToPixels(vectors);render(ctx)},false);var sprite=document.querySelector("#sprite");document.querySelector("#fade-in").addEventListener("click",function(){var start=0,end=1;var transition=new Transition(5e3,equation,function(delta){sprite.style.opacity=lerp(start,end,delta)});transition.start()},false);document.querySelector("#fade-out").addEventListener("click",function(){var start=1,end=0;var transition=new Transition(5e3,equation,function(delta){sprite.style.opacity=lerp(start,end,delta)});transition.start()},false);document.querySelector("#rise").addEventListener("click",function(){var start=800,end=100;sprite.style.opacity=1;var transition=new Transition(5e3,equation,function(delta){sprite.style.top=lerp(start,end,delta)+"px"});transition.start()},false);document.querySelector("#fall").addEventListener("click",function(){var start=100,end=800;sprite.style.opacity=1;var transition=new Transition(5e3,equation,function(delta){sprite.style.top=lerp(start,end,delta)+"px"});transition.start()},false)}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "requirebin-sketch", | |
"version": "1.0.0", | |
"dependencies": { | |
"transition": "0.1.1", | |
"elements": "0.5.0" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id="curves"></canvas> | |
<div id="sprite"></div> | |
<div id="curve"></div> | |
<div id="controls"> | |
<button id="fade-in">Animate Opacity (0 - 1)</button> | |
<button id="fade-out">Animate Opacity (1 - 0)</button> | |
<button id="fall">Animate Top (100 - 800)</button> | |
<button id="rise">Animate Top (800 - 100)</button> | |
<button id="add">Add Curve</button> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style> | |
body { | |
margin: 0; | |
padding: 0; | |
background-color: #222; | |
font-family: Arial; | |
} | |
#controls { | |
position: absolute; | |
top: 120px; | |
left: 20px; | |
width: 380px; | |
} | |
button { | |
display: inline-block; | |
margin: 0 5px 5px 0; | |
width: 180px; | |
height: 30px; | |
} | |
#curves { | |
top: 0; | |
left: 0; | |
position: absolute; | |
} | |
#curve { | |
color: white; | |
position: absolute; | |
top: 20px; | |
left: 20px; | |
font-size: 15px; | |
} | |
#sprite { | |
position: absolute; | |
top: 100px; | |
left: 500px; | |
background: red; | |
height: 40px; | |
width: 40px; | |
border-radius: 20px; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment