💡 Separate components
This commit is contained in:
parent
96b5475447
commit
b31eb91864
73
bundle.js
73
bundle.js
|
@ -5854,7 +5854,9 @@ return ancestorInfo.aTagInScope;case 'nobr':return ancestorInfo.nobrTagInScope;}
|
||||||
// with that -- otherwise we just start with the parent's owners.
|
// with that -- otherwise we just start with the parent's owners.
|
||||||
deepestCommon!==-1?childOwners[deepestCommon].getName()||UNKNOWN:[],ancestorOwnerNames,ancestorTag, // If we're warning about an invalid (non-parent) ancestry, add '...'
|
deepestCommon!==-1?childOwners[deepestCommon].getName()||UNKNOWN:[],ancestorOwnerNames,ancestorTag, // If we're warning about an invalid (non-parent) ancestry, add '...'
|
||||||
invalidAncestor?['...']:[],childOwnerNames,childTag).join(' > ');var warnKey=!!invalidParent+'|'+childTag+'|'+ancestorTag+'|'+ownerInfo;if(didWarn[warnKey]){return;}didWarn[warnKey]=true;if(invalidParent){var info='';if(ancestorTag==='table'&&childTag==='tr'){info+=' Add a <tbody> to your code to match the DOM tree generated by '+'the browser.';}process.env.NODE_ENV!=='production'?warning(false,'validateDOMNesting(...): <%s> cannot appear as a child of <%s>. '+'See %s.%s',childTag,ancestorTag,ownerInfo,info):undefined;}else {process.env.NODE_ENV!=='production'?warning(false,'validateDOMNesting(...): <%s> cannot appear as a descendant of '+'<%s>. See %s.',childTag,ancestorTag,ownerInfo):undefined;}}};validateDOMNesting.ancestorInfoContextKey='__validateDOMNesting_ancestorInfo$'+Math.random().toString(36).slice(2);validateDOMNesting.updatedAncestorInfo=updatedAncestorInfo; // For testing
|
invalidAncestor?['...']:[],childOwnerNames,childTag).join(' > ');var warnKey=!!invalidParent+'|'+childTag+'|'+ancestorTag+'|'+ownerInfo;if(didWarn[warnKey]){return;}didWarn[warnKey]=true;if(invalidParent){var info='';if(ancestorTag==='table'&&childTag==='tr'){info+=' Add a <tbody> to your code to match the DOM tree generated by '+'the browser.';}process.env.NODE_ENV!=='production'?warning(false,'validateDOMNesting(...): <%s> cannot appear as a child of <%s>. '+'See %s.%s',childTag,ancestorTag,ownerInfo,info):undefined;}else {process.env.NODE_ENV!=='production'?warning(false,'validateDOMNesting(...): <%s> cannot appear as a descendant of '+'<%s>. See %s.',childTag,ancestorTag,ownerInfo):undefined;}}};validateDOMNesting.ancestorInfoContextKey='__validateDOMNesting_ancestorInfo$'+Math.random().toString(36).slice(2);validateDOMNesting.updatedAncestorInfo=updatedAncestorInfo; // For testing
|
||||||
validateDOMNesting.isTagValidInContext=function(tag,ancestorInfo){ancestorInfo=ancestorInfo||emptyAncestorInfo;var parentInfo=ancestorInfo.parentTag;var parentTag=parentInfo&&parentInfo.tag;return isTagValidWithParent(tag,parentTag)&&!findInvalidAncestorForTag(tag,ancestorInfo);};}module.exports=validateDOMNesting;}).call(this,require('_process'));},{"./Object.assign":51,"_process":28,"fbjs/lib/emptyFunction":8,"fbjs/lib/warning":27}],158:[function(require,module,exports){'use strict';module.exports=require('./lib/React');},{"./lib/React":53}],159:[function(require,module,exports){'use strict' /**
|
validateDOMNesting.isTagValidInContext=function(tag,ancestorInfo){ancestorInfo=ancestorInfo||emptyAncestorInfo;var parentInfo=ancestorInfo.parentTag;var parentTag=parentInfo&&parentInfo.tag;return isTagValidWithParent(tag,parentTag)&&!findInvalidAncestorForTag(tag,ancestorInfo);};}module.exports=validateDOMNesting;}).call(this,require('_process'));},{"./Object.assign":51,"_process":28,"fbjs/lib/emptyFunction":8,"fbjs/lib/warning":27}],158:[function(require,module,exports){'use strict';module.exports=require('./lib/React');},{"./lib/React":53}],159:[function(require,module,exports){'use strict';var _createClass=(function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value" in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};})();Object.defineProperty(exports,"__esModule",{value:true});exports.App=undefined;var _react=require('react');var React=_interopRequireWildcard(_react);var _controls=require('./controls');var _fractal=require('./fractal');var _ifs=require('./ifs');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else {var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&((typeof call==="undefined"?"undefined":_typeof(call))==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+(typeof superClass==="undefined"?"undefined":_typeof(superClass)));}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;} /**
|
||||||
|
* Render the app sidebar and fractal display
|
||||||
|
*/var App=exports.App=(function(_React$Component){_inherits(App,_React$Component);function App(props){_classCallCheck(this,App);var _this=_possibleConstructorReturn(this,Object.getPrototypeOf(App).call(this,props));_this.state={};return _this;}_createClass(App,[{key:'render',value:function render(){return React.createElement('div',{className:'split'},React.createElement(_controls.Controls,null),React.createElement(_fractal.Fractal,{system:_ifs.sierpinski}));}}]);return App;})(React.Component);},{"./controls":161,"./fractal":162,"./ifs":163,"react":158}],160:[function(require,module,exports){'use strict' /**
|
||||||
* Choose an index at random among a list of weights,
|
* Choose an index at random among a list of weights,
|
||||||
* more weighted indices have a greater proability to be chosen
|
* more weighted indices have a greater proability to be chosen
|
||||||
*
|
*
|
||||||
|
@ -5869,14 +5871,71 @@ validateDOMNesting.isTagValidInContext=function(tag,ancestorInfo){ancestorInfo=a
|
||||||
* @param {Array} transforms List of available transforms
|
* @param {Array} transforms List of available transforms
|
||||||
* @param {Array} weights Probability weights for each transform
|
* @param {Array} weights Probability weights for each transform
|
||||||
* @return {Array} Generated points
|
* @return {Array} Generated points
|
||||||
*/var applyChaos=exports.applyChaos=function applyChaos(point,iterations,transforms,weights){var points=[];if(weights===undefined){weights=Array.apply(null,Array(transforms.length)).map(function(){return 1/transforms.length;});}while(iterations--){var index=chooseIndex(weights);point=transforms[index](point);points.push(point);}return points;};},{}],160:[function(require,module,exports){'use strict';var _slicedToArray=(function(){function sliceIterator(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err) {_d=true;_e=err;}finally {try{if(!_n&&_i["return"])_i["return"]();}finally {if(_d)throw _e;}}return _arr;}return function(arr,i){if(Array.isArray(arr)){return arr;}else if(Symbol.iterator in Object(arr)){return sliceIterator(arr,i);}else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};})();var _createClass=(function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value" in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};})();Object.defineProperty(exports,"__esModule",{value:true});exports.Fractal=undefined;var _react=require('react');var React=_interopRequireWildcard(_react);var _chaos=require('./chaos');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else {var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i];}return arr2;}else {return Array.from(arr);}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&((typeof call==="undefined"?"undefined":_typeof(call))==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+(typeof superClass==="undefined"?"undefined":_typeof(superClass)));}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}var Fractal=exports.Fractal=(function(_React$Component){_inherits(Fractal,_React$Component);function Fractal(props){_classCallCheck(this,Fractal);var _this=_possibleConstructorReturn(this,Object.getPrototypeOf(Fractal).call(this,props));_this.state={zoom:200,dragging:false,center:null,points:null};return _this;}_createClass(Fractal,[{key:'wheel',value:function wheel(event){var zoom=this.state.zoom;var center=this.state.center;var height=this.ctx.canvas.height;var delta=event.deltaMode===0?event.deltaY/53:event.deltaY;var newZoom=zoom*Math.max(0,1-delta*.035); // which (unprojected) point does the mouse point on?
|
*/var applyChaos=exports.applyChaos=function applyChaos(point,iterations,transforms,weights){var points=[];if(weights===undefined){weights=Array.apply(null,Array(transforms.length)).map(function(){return 1/transforms.length;});}while(iterations--){var index=chooseIndex(weights);point=transforms[index](point);points.push(point);}return points;};},{}],161:[function(require,module,exports){'use strict';var _createClass=(function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value" in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};})();Object.defineProperty(exports,"__esModule",{value:true});exports.Controls=undefined;var _react=require('react');var React=_interopRequireWildcard(_react);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else {var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&((typeof call==="undefined"?"undefined":_typeof(call))==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+(typeof superClass==="undefined"?"undefined":_typeof(superClass)));}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;} /**
|
||||||
|
* Render app controls
|
||||||
|
*/var Controls=exports.Controls=(function(_React$Component){_inherits(Controls,_React$Component);function Controls(props){_classCallCheck(this,Controls);var _this=_possibleConstructorReturn(this,Object.getPrototypeOf(Controls).call(this,props));_this.state={};return _this;}_createClass(Controls,[{key:'render',value:function render(){return React.createElement('aside',null,React.createElement('header',null,React.createElement('a',{href:'/'},React.createElement('img',{src:'images/avatar.jpg',alt:'Photo de Mattéo'}),React.createElement('span',null,'Mattéo Delabre ✏️'),React.createElement('br',null),'Back to home')),React.createElement('h1',null,'The Chaos Game'),React.createElement('h3',null,'Creating fractals with the chaos game'),'Sommets ',React.createElement('input',{id:'vertices',type:'range',min:'3',max:'12',step:'1',defaultValue:'3'}),React.createElement('br',null),'Fraction 1/',React.createElement('input',{id:'fraction',type:'range',min:'1',max:'6',step:'0.01',defaultValue:'2'}));}}]);return Controls;})(React.Component);},{"react":158}],162:[function(require,module,exports){'use strict';var _slicedToArray=(function(){function sliceIterator(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err) {_d=true;_e=err;}finally {try{if(!_n&&_i["return"])_i["return"]();}finally {if(_d)throw _e;}}return _arr;}return function(arr,i){if(Array.isArray(arr)){return arr;}else if(Symbol.iterator in Object(arr)){return sliceIterator(arr,i);}else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};})();var _createClass=(function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value" in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};})();Object.defineProperty(exports,"__esModule",{value:true});exports.Fractal=undefined;var _react=require('react');var React=_interopRequireWildcard(_react);var _chaos=require('./chaos');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else {var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i];}return arr2;}else {return Array.from(arr);}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&((typeof call==="undefined"?"undefined":_typeof(call))==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+(typeof superClass==="undefined"?"undefined":_typeof(superClass)));}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;} /**
|
||||||
|
* Render a canvas element that draws a fractal out of a
|
||||||
|
* given iterated function system
|
||||||
|
*/var Fractal=(function(_React$Component){_inherits(Fractal,_React$Component);function Fractal(props){_classCallCheck(this,Fractal);var _this=_possibleConstructorReturn(this,Object.getPrototypeOf(Fractal).call(this,props));_this.state={zoom:30,dragging:false,center:null,points:null};return _this;} /**
|
||||||
|
* Adjust zooming level and center so that wheeling the mouse
|
||||||
|
* on given point zooms around it
|
||||||
|
*
|
||||||
|
* @param {WheelEvent} event Mouse event
|
||||||
|
* @return {null}
|
||||||
|
*/_createClass(Fractal,[{key:'wheel',value:function wheel(event){var zoom=this.state.zoom;var center=this.state.center;var height=this.ctx.canvas.height;var delta=event.deltaMode===0?event.deltaY/53:event.deltaY;var newZoom=zoom*Math.max(0,1-delta*.035); // which (unprojected) point does the mouse point on?
|
||||||
var mouse=[(event.nativeEvent.offsetX-center[0])/zoom,(height-event.nativeEvent.offsetY-center[1])/zoom]; // we need to set the center so that `mouse` stays at
|
var mouse=[(event.nativeEvent.offsetX-center[0])/zoom,(height-event.nativeEvent.offsetY-center[1])/zoom]; // we need to set the center so that `mouse` stays at
|
||||||
// the same position on screen, i.e (vectorially):
|
// the same position on screen, i.e (vectorially):
|
||||||
// mouse * newZoom + newCenter = mouse * zoom + center
|
// mouse * newZoom + newCenter = mouse * zoom + center
|
||||||
// => newCenter = mouse * zoom - mouse * newZoom + center
|
// => newCenter = mouse * zoom - mouse * newZoom + center
|
||||||
this.setState({zoom:newZoom,center:[mouse[0]*zoom-mouse[0]*newZoom+center[0],mouse[1]*zoom-mouse[1]*newZoom+center[1]]},this.draw);event.preventDefault();}},{key:'mouseDown',value:function mouseDown(event){this.setState({dragging:[event.nativeEvent.offsetX,event.nativeEvent.offsetY]});}},{key:'mouseUp',value:function mouseUp(){this.setState({dragging:false});}},{key:'mouseMove',value:function mouseMove(event){var dragging=this.state.dragging;var center=this.state.center;if(dragging!==false){var newMouse=[event.nativeEvent.offsetX,event.nativeEvent.offsetY];var movement=[newMouse[0]-dragging[0],newMouse[1]-dragging[1]];this.setState({dragging:newMouse,center:[center[0]+movement[0],center[1]-movement[1]]},this.draw);event.preventDefault();}}},{key:'draw',value:function draw(){var width=this.ctx.canvas.width;var height=this.ctx.canvas.height;var zoom=this.state.zoom;var center=this.state.center;var points=this.state.points; // do not plot (very) small sizes
|
this.setState({zoom:newZoom,center:[mouse[0]*zoom-mouse[0]*newZoom+center[0],mouse[1]*zoom-mouse[1]*newZoom+center[1]]},this.draw);event.preventDefault();} /**
|
||||||
if(width<1){return;}this.ctx.clearRect(0,0,width,height); // do the chaos game
|
* Save the mouse coordinates when we click down,
|
||||||
var image=this.ctx.getImageData(0,0,width,height);var length=points.length;var color=[0,0,0];for(var i=50;i<length;i+=1){var x=Math.floor(points[i][0]*zoom+center[0]);var y=height-Math.floor(points[i][1]*zoom+center[1]);if(x>=0&&x<width&&y>=0&&y<height){var index=(y*width+x)*4;image.data[index]=color[0];image.data[index+1]=color[1];image.data[index+2]=color[2];image.data[index+3]=255;}}this.ctx.putImageData(image,0,0);} // this is dirty. TODO: make it less coupled
|
* for use by `mouseMove()`
|
||||||
},{key:'getSize',value:function getSize(){var wrapping=document.querySelector('#content');return [wrapping.clientWidth,wrapping.clientHeight];}},{key:'resize',value:function resize(){var _getSize=this.getSize();var _getSize2=_slicedToArray(_getSize,2);this.ctx.canvas.width=_getSize2[0];this.ctx.canvas.height=_getSize2[1];this.draw();}},{key:'calculate',value:function calculate(){return _chaos.applyChaos.apply(undefined,[[0,0],200000].concat(_toConsumableArray(this.props.system)));}},{key:'componentDidMount',value:function componentDidMount(){window.addEventListener('resize',this.resize.bind(this));this.setState({center:this.getSize().map(function(x){return Math.floor(x/2);}),points:this.calculate()},this.resize.bind(this));}},{key:'componentWillUnmount',value:function componentWillUnmount(){window.removeEventListener('resize',this.resize.bind(this));}},{key:'shouldComponentUpdate',value:function shouldComponentUpdate(){return false;}},{key:'render',value:function render(){var _this2=this;return React.createElement('canvas',{ref:function ref(canvas){return _this2.ctx=canvas.getContext('2d');},onWheel:this.wheel.bind(this),onMouseDown:this.mouseDown.bind(this),onMouseUp:this.mouseUp.bind(this),onMouseMove:this.mouseMove.bind(this)});}}]);return Fractal;})(React.Component);},{"./chaos":159,"react":158}],161:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var linearTransform=function linearTransform(a,b,c,d,e,f){return function(point){return [a*point[0]+b*point[1]+e,c*point[0]+d*point[1]+f];};};var polygonTransforms=function polygonTransforms(vertices,frac){return vertices.map(function(vertex){return linearTransform(frac,0,0,frac,vertex[0]*(frac-1),vertex[1]*(frac-1));});};var barnsley=exports.barnsley=[[linearTransform(0,0,0,0.16,0,0),linearTransform(.85,.04,-.04,.85,0,1.6),linearTransform(.20,-.26,.23,.22,0,1.6),linearTransform(-.15,.28,.26,.24,0,.44)],[.01,.85,.07,.07]];var sierpinski=exports.sierpinski=[polygonTransforms([[.866,.5],[-.866,.5],[0,-1]],1/2),[1/3,1/3,1/3]];},{}],162:[function(require,module,exports){'use strict';var _fractal=require('./fractal');var _react=require('react');var React=_interopRequireWildcard(_react);var _reactDom=require('react-dom');var _ifs=require('./ifs');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else {var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}} // eslint-disable-line no-unused-vars
|
*
|
||||||
(0,_reactDom.render)(React.createElement(_fractal.Fractal,{system:_ifs.barnsley}),document.querySelector('#content'));},{"./fractal":160,"./ifs":161,"react":158,"react-dom":29}]},{},[162]);
|
* @param {MouseEvent} event Mouse event
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'mouseDown',value:function mouseDown(event){this.setState({dragging:[event.nativeEvent.offsetX,event.nativeEvent.offsetY]});} /**
|
||||||
|
* Save the fact that the mouse was released
|
||||||
|
*
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'mouseUp',value:function mouseUp(){this.setState({dragging:false});} /**
|
||||||
|
* When moving the mouse while clicking, pan the figure
|
||||||
|
*
|
||||||
|
* @param {MouseEvent} event Mouse event
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'mouseMove',value:function mouseMove(event){var dragging=this.state.dragging;var center=this.state.center;if(dragging!==false){var newMouse=[event.nativeEvent.offsetX,event.nativeEvent.offsetY];var movement=[newMouse[0]-dragging[0],newMouse[1]-dragging[1]]; // move the center by given offset and redraw
|
||||||
|
this.setState({dragging:newMouse,center:[center[0]+movement[0],center[1]-movement[1]]},this.draw);event.preventDefault();}} /**
|
||||||
|
* Redraw `points` on the canvas, scaled with given
|
||||||
|
* `zoom` and based on current `center`
|
||||||
|
*
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'draw',value:function draw(){var width=this.ctx.canvas.width;var height=this.ctx.canvas.height;var zoom=this.state.zoom;var center=this.state.center;var points=this.state.points; // do not plot (very) small sizes
|
||||||
|
if(width<1){return;}this.ctx.clearRect(0,0,width,height); // fill each point in `points` skipping the first 50 ones
|
||||||
|
var image=this.ctx.getImageData(0,0,width,height);var length=points.length;var color=[0,0,0];for(var i=50;i<length;i+=1){var x=Math.floor(points[i][0]*zoom+center[0]);var y=height-Math.floor(points[i][1]*zoom+center[1]);if(x>=0&&x<width&&y>=0&&y<height){var index=(y*width+x)*4;image.data[index]=color[0];image.data[index+1]=color[1];image.data[index+2]=color[2];image.data[index+3]=255;}}this.ctx.putImageData(image,0,0);} /**
|
||||||
|
* Get the container size
|
||||||
|
*
|
||||||
|
* @return {Array} Width and height of the container
|
||||||
|
*/},{key:'getSize',value:function getSize(){return [this.container.clientWidth,this.container.clientHeight];} /**
|
||||||
|
* Update the canvas size to its parent size
|
||||||
|
* and redraw
|
||||||
|
*
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'resize',value:function resize(){var _getSize=this.getSize();var _getSize2=_slicedToArray(_getSize,2);this.ctx.canvas.width=_getSize2[0];this.ctx.canvas.height=_getSize2[1];this.draw();} /**
|
||||||
|
* Calculate points with current system
|
||||||
|
*
|
||||||
|
* @return {Array} Points to be drawn
|
||||||
|
*/},{key:'calculate',value:function calculate(){return _chaos.applyChaos.apply(undefined,[[0,0],this.props.iterations].concat(_toConsumableArray(this.props.system)));} /**
|
||||||
|
* Setup resize listener and make initial drawing
|
||||||
|
* when the component has been mounted
|
||||||
|
*
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'componentDidMount',value:function componentDidMount(){window.addEventListener('resize',this.resize.bind(this));this.setState({center:this.getSize().map(function(x){return Math.floor(x/2);}),points:this.calculate()},this.resize.bind(this));} /**
|
||||||
|
* Remove the resize listener before unmounting the component
|
||||||
|
*
|
||||||
|
* @return {null}
|
||||||
|
*/},{key:'componentWillUnmount',value:function componentWillUnmount(){window.removeEventListener('resize',this.resize.bind(this));} /**
|
||||||
|
* Never create a new canvas
|
||||||
|
*/},{key:'shouldComponentUpdate',value:function shouldComponentUpdate(){return false;} /**
|
||||||
|
* Create a canvas with correct listeners
|
||||||
|
*/},{key:'render',value:function render(){var _this2=this;return React.createElement('div',{id:'content',ref:function ref(div){return _this2.container=div;}},React.createElement('canvas',{ref:function ref(canvas){return _this2.ctx=canvas.getContext('2d');},onWheel:this.wheel.bind(this),onMouseDown:this.mouseDown.bind(this),onMouseUp:this.mouseUp.bind(this),onMouseMove:this.mouseMove.bind(this)}));}}]);return Fractal;})(React.Component);Fractal.defaultProps={iterations:200000,system:[[],[]]};exports.Fractal=Fractal;},{"./chaos":160,"react":158}],163:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var linearTransform=function linearTransform(a,b,c,d,e,f){return function(point){return [a*point[0]+b*point[1]+e,c*point[0]+d*point[1]+f];};};var polygonTransforms=function polygonTransforms(vertices,frac){return vertices.map(function(vertex){return linearTransform(frac,0,0,frac,vertex[0]*(frac-1),vertex[1]*(frac-1));});};var regularVertices=function regularVertices(count){var step=2*Math.PI/count;var initial=-Math.atan(Math.sin(step)/(Math.cos(step)-1));var result=[];for(var i=0;i<count;i+=1){var current=step*i+initial;result.push([Math.cos(current)*10,Math.sin(current)*10]);}return result;};var barnsley=exports.barnsley=[[linearTransform(0,0,0,0.16,0,0),linearTransform(.85,.04,-.04,.85,0,1.6),linearTransform(.20,-.26,.23,.22,0,1.6),linearTransform(-.15,.28,.26,.24,0,.44)],[.01,.85,.07,.07]];var sierpinski=exports.sierpinski=[polygonTransforms(regularVertices(3),1/2),[1/3,1/3,1/3]];},{}],164:[function(require,module,exports){'use strict';var _app=require('./app');var _react=require('react');var React=_interopRequireWildcard(_react);var _reactDom=require('react-dom');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else {var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}(0,_reactDom.render)(React.createElement(_app.App,null),document.querySelector('#react')); // eslint-disable-line no-unused-vars
|
||||||
|
},{"./app":159,"react":158,"react-dom":29}]},{},[164]);
|
||||||
|
|
||||||
|
|
22
index.html
22
index.html
|
@ -9,26 +9,8 @@
|
||||||
<link href="https://matteodelabre.me/styles/demos.css" rel="stylesheet">
|
<link href="https://matteodelabre.me/styles/demos.css" rel="stylesheet">
|
||||||
<link href="styles/index.css" rel="stylesheet">
|
<link href="styles/index.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body class="split">
|
<body>
|
||||||
<aside>
|
<div id="react"></div>
|
||||||
<header>
|
|
||||||
<a href="/">
|
|
||||||
<img src="images/avatar.jpg" alt="Photo de Mattéo" />
|
|
||||||
<span>Mattéo Delabre ✏️</span><br />
|
|
||||||
Back to home
|
|
||||||
</a>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<h1>The Chaos Game</h1>
|
|
||||||
<h3>Creating fractals with the chaos game</h3>
|
|
||||||
|
|
||||||
Sommets <input id="vertices" type="range" min="3" max="12" step="1" value="3"><br>
|
|
||||||
Fraction 1/<input id="fraction" type="range" min="1" max="6" step="0.01" value="2">
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<div id="content">
|
|
||||||
<canvas id="plotting"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="bundle.js"></script>
|
<script src="bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Controls } from './controls';
|
||||||
|
import { Fractal } from './fractal';
|
||||||
|
import { sierpinski } from './ifs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the app sidebar and fractal display
|
||||||
|
*/
|
||||||
|
export class App extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <div className="split">
|
||||||
|
<Controls />
|
||||||
|
<Fractal system={sierpinski} />
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render app controls
|
||||||
|
*/
|
||||||
|
export class Controls extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <aside>
|
||||||
|
<header>
|
||||||
|
<a href="/">
|
||||||
|
<img src="images/avatar.jpg" alt="Photo de Mattéo" />
|
||||||
|
<span>Mattéo Delabre ✏️</span><br />
|
||||||
|
Back to home
|
||||||
|
</a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<h1>The Chaos Game</h1>
|
||||||
|
<h3>Creating fractals with the chaos game</h3>
|
||||||
|
|
||||||
|
Sommets <input id="vertices" type="range" min="3" max="12" step="1" defaultValue="3" /><br />
|
||||||
|
Fraction 1/<input id="fraction" type="range" min="1" max="6" step="0.01" defaultValue="2" />
|
||||||
|
</aside>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { Fractal } from './fractal';
|
import { App } from './app';
|
||||||
import * as React from 'react'; // eslint-disable-line no-unused-vars
|
import * as React from 'react'; // eslint-disable-line no-unused-vars
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import { barnsley } from './ifs';
|
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Fractal system={barnsley} />,
|
<App />,
|
||||||
document.querySelector('#content')
|
document.querySelector('#react')
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
* Styles for chaos game
|
* Styles for chaos game
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#react {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue