/
image.js
151 lines (131 loc) · 4.53 KB
/
image.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
var Crafty = require('../core/core.js');
//
// Define some variables required for webgl
var fs = require('fs');
Crafty.defaultShader("Image", new Crafty.WebGLShader(
fs.readFileSync(__dirname + '/shaders/sprite.vert', 'utf8'),
fs.readFileSync(__dirname + '/shaders/sprite.frag', 'utf8'),
[
{ name: "aPosition", width: 2 },
{ name: "aOrientation", width: 3 },
{ name: "aLayer", width: 2 },
{ name: "aTextureCoord", width: 2 }
],
function(e, _entity) {
var pos = e.pos;
// Write texture coordinates
e.program.writeVector("aTextureCoord",
0, 0,
0, pos._h,
pos._w, 0,
pos._w, pos._h
);
}
));
/**@
* #Image
* @category Graphics
* @kind Component
*
* Draw an image with or without repeating (tiling).
*/
Crafty.c("Image", {
_repeat: "repeat",
ready: false,
init: function () {
this.bind("Draw", this._drawImage);
this.bind("LayerAttached", this._setupImage);
},
remove: function() {
this.unbind("LayerAttached", this._setupImage);
this.unbind("Draw", this._drawImage);
},
/**@
* #.image
* @comp Image
* @kind Method
*
* @trigger Invalidate - when the image is loaded
* @sign public this .image(String url[, String repeat])
* @param url - URL of the image
* @param repeat - If the image should be repeated to fill the entity. This follows CSS syntax: (`"no-repeat", "repeat", "repeat-x", "repeat-y"`), but defaults to `no-repeat`.
*
* Draw the specified image.
*
* @note The default value of repeat is `no-repeat`, which is different than the standard CSS default
*
* If the width and height are `0` and repeat is set to `no-repeat` the width and
* height will automatically assume that of the image. This is an
* easy way to create an image without needing sprites.
*
* If set to `no-repeat` and given dimensions larger than that of the image,
* the exact appearance will depend on what renderer (WebGL, DOM, or Canvas) is used.
*
* @example
* Will default to no-repeat. Entity width and height will be set to the images width and height
* ~~~
* var ent = Crafty.e("2D, DOM, Image").image("myimage.png");
* ~~~
* Create a repeating background.
* ~~~
* var bg = Crafty.e("2D, DOM, Image")
* .attr({w: Crafty.viewport.width, h: Crafty.viewport.height})
* .image("bg.png", "repeat");
* ~~~
*
* @see Crafty.sprite
*/
image: function (url, repeat) {
this.__image = url;
this._repeat = repeat || "no-repeat";
this.img = Crafty.asset(url);
if (!this.img) {
this.img = new Image();
Crafty.asset(url, this.img);
this.img.src = url;
var self = this;
this.img.onload = function () {
self._setupImage(self._drawLayer);
};
} else {
this._setupImage(this._drawLayer);
}
this.trigger("Invalidate");
return this;
},
// called on image change or layer attachment
_setupImage: function(layer){
if (!this.img || !layer) return;
if (layer.type === "Canvas") {
this._pattern = this._drawContext.createPattern(this.img, this._repeat);
} else if (layer.type === "WebGL") {
this._establishShader("image:" + this.__image, Crafty.defaultShader("Image"));
this.program.setTexture( this._drawLayer.makeTexture(this.__image, this.img, (this._repeat!=="no-repeat")));
}
if (this._repeat === "no-repeat") {
this.w = this.w || this.img.width;
this.h = this.h || this.img.height;
}
this.ready = true;
this.trigger("Invalidate");
},
_drawImage: function(e){
if (e.type === "canvas") {
//skip if no image
if (!this.ready || !this._pattern) return;
var context = e.ctx;
context.fillStyle = this._pattern;
context.save();
context.translate(e.pos._x, e.pos._y);
context.fillRect(0, 0, e.pos._w, e.pos._h);
context.restore();
} else if (e.type === "DOM") {
if (this.__image) {
e.style.backgroundImage = "url(" + this.__image + ")";
e.style.backgroundRepeat = this._repeat;
}
} else if (e.type === "webgl") {
e.program.draw(e, this);
}
}
});