
рдХрд▓ рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдХреИрдирд╡рд╕ рдкрд░ рдПрдХ "рдЖрдХрд╛рд╢рдЧрдВрдЧрд╛" рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рд╡рд┐рд╖рдп, "
рдж рд╣рд┐рд╕реНрдЯреНрд░реА рдСрдл рдП рд╣рдмрд╕реНрдкреЛрд░ " рдерд╛, рдЬреЛ рдХрд┐ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдФрд░ рдЕрдкрдиреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рд╕реЗ рдореБрдЭреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд░рддрд╛ рдерд╛ред рдореИрдВрдиреЗ рд╕реЛрдЪрд╛, рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдЕрдВрдд рддрдХ, рдореИрдВрдиреЗ
рд╣реИрдмреЗ рдкрд░ рдирдИ рдЪреАрдЬреЗрдВ рдирд╣реАрдВ рд▓рд┐рдЦреАрдВ, рд▓реЗрдХрд┐рди, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦрддреЗ рд╣реИрдВ, рдпрд╣ рдЯреВрдЯ рдЧрдпрд╛)
рдЗрд╕рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж
рдХрд┐рдмрд┐рдЬрд╝реЙрдЗрдбрд╕ ред
рд╡рд┐рд╖рдп рдореЗрдВ рдЖрдк
LibCanvas рдХреЗ
рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдПрдХ рд╕реНрдЯрд╛рд░ рд╕рд┐рд╕реНрдЯрдо рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд┐рд╡рд░рдг рджреЗрдЦреЗрдВрдЧреЗред рддреЗрдЬ, рдЕрдиреБрдХреВрд▓рд┐рдд, рд╕рдВрдХреНрд╖рд┐рдкреНрддред
рдореБрдЭреЗ рддреБрд░рдВрдд рдХрд╣рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдЯреАрдХреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реИред рдХрд╛рд░рдг рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ - рдЬрдм рдореИрдВ рдХрд▓ рд╣реЙрдмрд┐рдЯ рд╕реЗ 3 рдмрдЬреЗ рдЖрдпрд╛, рдореИрдВрдиреЗ рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╕рдордп рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА - рд╕рдм рдХреБрдЫ рдХреЗ рд▓рд┐рдП
рдПрдХ рдШрдВрдЯреЗ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ ред рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ, рдореИрдВрдиреЗ рд╕реБрдмрд╣ рдирд╛рд╢реНрддреЗ рдореЗрдВ рдХрд░реНрд╕рд░ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдпреЗ рд╡рд┐рд╡рд░рдг рд╣реИрдВ) рдореИрдВ рдШрдВрдЯреЗ рд╕реЗ рдорд┐рд▓рд╛ред
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦрдХ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдореБрдЭреЗ "рдЕрдкрдиреЗ рджреЗрд╡ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рд╡рд░реНрдЪреБрдПрд▓рд╣реЛрд╕реНрдЯ, рдЧрд┐рдЯ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА" рдФрд░ рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рдирд╣реАрдВ рдмрдирд╛рдирд╛ рд╣реИ - рдпрд╣ рд╕рдм рдореЗрд░реЗ рд╕рд╛рде
libcanvas.github.com рдХреА рд▓рдбрд╝рд╛рдИ рдореЗрдВ рд╣рдореЗрд╢рд╛ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рдорд╛рдирдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рд▓рд┐рдпрд╛ рдФрд░ рддреБрд░рдВрдд рдпреБрджреНрдз рдореЗрдВ рдЪрд▓рд╛ рдЧрдпрд╛,
рдЖрдХрд╛рд╢ рдХреЛ рдПрдХ рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛, рддрд╛рдХрд┐ рдЕрдХреЗрд▓реЗ рдХрд╛рд▓реЗ рдмрд╛рд▓реЛрдВ рдХреЛ рди рджреЗрдЦреЗрдВ:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>LibCanvas :: Solar</title>
<link href="/files/styles.css" rel="stylesheet" />
<style> html, body { background: url(im/sky.png) } </style>
<script src="/files/js/atom.js"></script>
<script src="/files/js/libcanvas.js"></script>
</head>
<body>
<p><a href="/">Return to index</a></p>
<script>
new function () {
LibCanvas.extract();
atom.dom(function () {
new Solar.Controller();
});
};
</script>
<script src="js/controller.js"></script>
</body>
</html>
. тАФ , , . тАФ
. , .
atom.declare('Solar.Controller', {
initialize: function () {
this.size = new Size(840, 840);
this.app = new App({ size: this.size });
atom.ImagePreloader.run({
planets: 'im/planets.png',
sun : 'im/sun.png'
}, this.start.bind(this));
},
start: function (images) {
this.app.resources.set( 'images', images );
}
});
. , - .
intersection: all
,
invoke: true
,
onUpdate
initialize: function () {
this.geoLayer = this.app.createLayer({
name: 'geo',
invoke: true,
intersection: 'all',
zIndex: 2
});
, тАФ . . , ,
App.Element
, :
atom.declare('Solar.Sun', App.Element, {
renderTo: function (ctx, resources) {
ctx.drawImage({
image : resources.get('images').get('sun'),
center: this.shape.center
});
}
});
:
start: function (images) {
this.sun = new Solar.Sun(this.geoLayer, {
shape: new Circle(this.app.rectangle.center, 50)
});
:

тАФ . 12 . 90 , 26 . 40 , 20 .
atom.declare('Solar.Controller', {
names : 'Selene Mimas Ares Enceladus Tethys Dione Zeus Rhea Titan Janus Hyperion Iapetus'
.split(' '),
start: function (images) {
for (var i = 12; i--;) {
var planet = new Solar.Planet(this.geoLayer, {
sun : this.sun,
radius: 90 + i * 26,
time : 40 + i * 20,
image : i,
zIndex: 0,
name : this.names[i]
});
}
тАФ , .
this.center = this.solarCenter.clone();
this.center.move([ this.radius, 0 ]);
тАФ 360
'time'
360/1000 :
this.rotatePerMs = (360).degree() / 1000 / this.settings.get('time');
тАФ :
getImagePart: function () {
var x = this.settings.get('image');
return this.layer.app.resources.get('images')
.get('planets')
.sprite(new Rectangle([ x*this.size.width,0 ],this.size));
},
тАФ
LibCanvas.Point.rotate
.
normalizeAngle
, 0 360 .
rotate: function (angle) {
if (angle == null) angle = Number.random(0, 360).degree();
this.angle = (this.angle + angle).normalizeAngle();
this.center.rotate(angle, this.solarCenter);
return this;
},
тАФ
onUpdate
, , .
onUpdate
,
renderTo
тАФ LibCanvas , .
onUpdate: function (time) {
this.rotate(time * this.rotatePerMs);
this.redraw();
},
тАФ :
renderTo: function (ctx) {
ctx.drawImage({
image : this.image,
center: this.center,
angle : this.angle
});
}
atom.declare('Solar.Planet', App.Element, {
angle: 0,
configure: function () {
this.size = new Size(26, 26);
this.center = this.solarCenter.clone();
this.center.move([ this.radius, 0 ]);
this.rotatePerMs = (360).degree() / 1000 / this.settings.get('time');
this.shape = new Circle(this.center, this.size.width/2);
this.image = this.getImagePart();
this.rotate();
},
getImagePart: function () {
var x = this.settings.get('image');
return this.layer.app.resources.get('images')
.get('planets')
.sprite(new Rectangle([x*this.size.width,0],this.size));
},
get radius () {
return this.settings.get('radius');
},
get solarCenter () {
return this.settings.get('sun').shape.center;
},
rotate: function (angle) {
if (angle == null) angle = Number.random(0, 360).degree();
this.angle = (this.angle + angle).normalizeAngle();
this.center.rotate(angle, this.solarCenter);
return this;
},
onUpdate: function (time) {
this.rotate(time * this.rotatePerMs);
this.redraw();
},
renderTo: function (ctx) {
ctx.drawImage({
image : this.image,
center: this.center,
angle : this.angle
});
}
});
:

тАФ . , .
-, . тАФ , . тАФ , .
.
onUpdate
, . - , , . , ,
initialize: function () {
this.orbitLayer = this.app.createLayer({
name: 'orbit',
intersection: 'manual',
zIndex: 1
});
start: function (images) {
for (var i = 12; i--;) {
var planet = new Solar.Planet(this.geoLayer, {
});
planet.createOrbit(this.orbitLayer, i);
}
createOrbit: function (layer, z) {
return this.orbit = new Solar.Orbit(layer, { planet: this, zIndex: z });
},
.
Circle
, ,
renderTo
stroke' . ,
clearPrevious
, тАФ BoundingRectangle,
ctx.clear(this.shape, true)
:
atom.declare('Solar.Orbit', App.Element, {
configure: function () {
this.shape = new Circle(this.planet.solarCenter, this.planet.radius);
},
get planet () {
return this.settings.get('planet');
},
clearPrevious: function (ctx) {
ctx.clear(this.shape, true);
},
renderTo: function (ctx, resources) {
ctx.stroke(this.shape, 'rgba(0,192,255,0.5)');
}
});
, .

LibCanvas.Mouse
, dom-
LibCanvas.App.MouseHandler
,
start: function (images) {
var mouse, mouseHandler;
mouse = new Mouse(this.app.container.bounds);
mouseHandler = new App.MouseHandler({ mouse: mouse, app: this.app });
this.app.resources.set({
images: images,
mouse : mouse,
mouseHandler: mouseHandler
});
for (var i = 12; i--;) {
var planet = new Solar.Planet(this.geoLayer, {
});
planet.createOrbit(this.orbitLayer, i);
mouseHandler.subscribe( planet );
mouseHandler.subscribe( planet.orbit );
}
}
, . . . .. . ,
isTriggerPoint
. 13 .
isTriggerPoint: function (point) {
var distance = this.planet.solarCenter.distanceTo(point);
return (this.planet.radius - distance).abs() < 13;
},
, , тАФ hover
Clickable
:
configure: function () {
new App.Clickable( this, this.redraw ).start();
},
renderTo: function (ctx, resources) {
if (this.hover) {
ctx.stroke(this.shape, 'rgba(255,64,64,0.8)');
} else {
ctx.stroke(this.shape, 'rgba(0,192,255,0.5)');
}
}

, . . , hover :
isHover: function () {
return this.hover || this.planet.hover;
},
renderTo: function (ctx, resources) {
if (this.isHover()) {
}
.. - ( ) тАФ
redraw
onUpdate
configure: function () {
new App.Clickable( this, this.redraw ).start();
},
onUpdate: function (time) {
if (this.orbit.isHover()) this.orbit.redraw();
},
hover . . . shape , shape . :
renderTo: function (ctx, resources) {
if (this.isHover()) {
ctx.save();
ctx.set({ strokeStyle: 'rgb(0,192,255)', lineWidth: 3 });
ctx.stroke(this.shape);
ctx.clear(this.planet.shape);
ctx.stroke(this.planet.shape);
ctx.restore();
} else {
ctx.stroke(this.shape, 'rgba(0,192,255,0.5)');
}
}
тАФ ┬л┬╗ , , , ┬л┬╗ . LibCanvas тАФ
saveCurrentBoundingShape
, , , . , :
saveCurrentBoundingShape: function () {
if (this.isHover()) {
this.previousBoundingShape = this.planet.shape.clone().grow(6);
} else {
this.previousBoundingShape = null;
}
return this;
},
. тАФ . тАФ , , :
clearPrevious: function (ctx) {
if (this.previousBoundingShape) {
ctx.save();
ctx.set({ lineWidth: 4 });
ctx.clear(this.previousBoundingShape);
ctx.clear(this.shape, true);
ctx.restore();
} else {
ctx.clear(this.shape, true);
}
},
:

, тАФ .
mouseover
mouseout
Solar.Planet
, , .. тАФ
mouseout
. , .
configure: function () {
this.mousePoint = this.layer.app.resources.get('mouse').point;
this.info = new Solar.Info(this.layer, { planet: this, zIndex: 1 });
},
checkStatus: function (visible) {
if (this.info.isVisible() != visible) {
this.info[visible ? 'show' : 'hide']();
}
},
onUpdate: function (time) {
this.checkStatus(this.isTriggerPoint(this.mousePoint));
if (this.info.isVisible()) this.info.updateShape(this.shape.center);
},
settings: { hidden: true }
тАФ LibCanvas. , , .
Solar.Info
, .
atom.declare('Solar.Info', App.Element, {
settings: { hidden: true },
get planet () {
return this.settings.get('planet');
},
configure: function () {
this.shape = new Rectangle(0,0,100,30);
},
updateShape: function (from) {
this.shape.moveTo(from).move([20,10])
},
show: function () {
this.settings.set({ hidden: false });
this.redraw();
},
hide: function () {
this.settings.set({ hidden: true });
this.redraw();
},
renderTo: function (ctx) {
ctx.fill(this.shape, '#002244');
ctx.text({
to : this.shape,
text : this.planet.settings.get('name'),
color: '#0ff',
align: 'center',
optimize: false,
padding: 3
})
}
});
:

, тАФ :
checkStatus: function (visible) {
if (this.info.isVisible() != visible) {
this.info[visible ? 'show' : 'hide']();
this.layer.dom.element.css('cursor', visible ? 'pointer' : 'default');
}
},
GitHub,
.
:
1.
2.
.
(program)
тАФ . 100%.
:

LibCanvas:

:

(/ ):
тАФ 100%, 44 fps:

LibCanvas тАФ 40%, 60 fps:

, , . , тАФ shocksilien@gmail.com