Skip to content

Commit c3e6c18

Browse files
Create NinePatch.js
1 parent c2e458b commit c3e6c18

1 file changed

Lines changed: 236 additions & 0 deletions

File tree

NinePatch.js

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
/*
2+
Constructor: NinePatch(srcImage, newWidth, newHeight)
3+
+ srcImage: (String) url of image.
4+
+ newWidth: (Number) new image's width
5+
+ newHeight: (Number) new image's height
6+
APIs:
7+
+ setSrcImage(srcImage)
8+
+ setWidth(newWidth)
9+
+ setHeight(newHeight)
10+
+ getSize => {url, width, height}: 'url' is the original image's url
11+
+ run => {url, width, height}: 'url' is the new image's url, which is scaled.
12+
*/
13+
14+
(function(document, window){
15+
var NinePatch = function(srcImage, newWidth, newHeight) {
16+
this.srcImage = srcImage;
17+
this.newWidth = newWidth;
18+
this.newHeight = newHeight;
19+
}
20+
21+
NinePatch.prototype.setSrcImage = function(srcImage) {
22+
this.srcImage = srcImage;
23+
}
24+
25+
NinePatch.prototype.setWidth = function(newWidth) {
26+
this.newWidth = newWidth;
27+
}
28+
29+
NinePatch.prototype.setHeight = function(newHeight) {
30+
this.newHeight = newHeight;
31+
}
32+
33+
NinePatch.prototype.getSize = function() {
34+
var self = this;
35+
return new Promise(function(resolve, reject) {
36+
var image = new Image();
37+
image.onload = function() {
38+
resolve({url: self.srcImage, width: image.width, height: image.height});
39+
};
40+
image.onerror = function(error) {
41+
reject(error);
42+
}
43+
image.src = srcImg;
44+
});
45+
}
46+
47+
NinePatch.prototype.run = function() {
48+
var self = this;
49+
return new Promise(function(resolve, reject){
50+
var canvas = document.createElement('canvas');
51+
var newCanvas = document.createElement('canvas');
52+
var context = canvas.getContext('2d');
53+
var newContext = newCanvas.getContext('2d');
54+
var image = new Image();
55+
56+
image.onload = function() {
57+
canvas.width = image.width;
58+
canvas.height = image.height;
59+
newCanvas.width = self.newWidth;
60+
newCanvas.height = self.newHeight;
61+
context.drawImage(image, 0, 0, image.width, image.height);
62+
63+
var offset = getOffsetFromCanvas(canvas, context);
64+
//console.log(offset);
65+
66+
// copy top-left corner, ignore 1px from the left
67+
var rootX = 1, rootY = 1;
68+
var newX = 0, newY = 0;
69+
if(offset.left - 1 > 0 && offset.top - 1 > 0) {
70+
var imageData = context.getImageData(rootX, rootY, offset.left - 1, offset.top - 1);
71+
newContext.putImageData(imageData, newX, newY);
72+
}
73+
74+
// copy top-right corner, ignore 1px from the right
75+
rootX = canvas.width - offset.right; rootY = 1;
76+
newX = newCanvas.width - offset.right; newY = 0;
77+
if(offset.right - 1 > 0 && offset.top - 1 > 0) {
78+
imageData = context.getImageData(rootX, rootY, offset.right - 1, offset.top - 1);
79+
newContext.putImageData(imageData, newX, newY);
80+
}
81+
82+
// copy bottom-right corner
83+
rootX = canvas.width - offset.right; rootY = canvas.height - offset.bottom;
84+
newX = newCanvas.width - offset.right; newY = newCanvas.height - offset.bottom;
85+
imageData = context.getImageData(rootX, rootY, offset.right - 1, offset.bottom - 1);
86+
newContext.putImageData(imageData, newX, newY);
87+
88+
// copy bottom-left corner
89+
rootX = 1; rootY = canvas.height - offset.bottom;
90+
newX = 0; newY = newCanvas.height - offset.bottom;
91+
if(offset.left - 1 > 0 && offset.bottom - 1 > 0) {
92+
imageData = context.getImageData(rootX, rootY, offset.left - 1, offset.bottom - 1);
93+
newContext.putImageData(imageData, newX, newY);
94+
}
95+
96+
// scale middle top
97+
rootX = offset.left; rootY = 1;
98+
if(offset.top - 1 > 0) {
99+
imageData = context.getImageData(rootX, rootY, 1, offset.top - 1);
100+
for(let x = offset.left - 1; x <= newCanvas.width - offset.right; x++) {
101+
newContext.putImageData(imageData, x, 0);
102+
}
103+
}
104+
105+
// scale middle bottom
106+
rootX = offset.left; rootY = canvas.height - offset.bottom;
107+
if(offset.bottom - 1 > 0) {
108+
imageData = context.getImageData(rootX, rootY, 1, offset.bottom - 1);
109+
for(let x = offset.left - 1; x <= newCanvas.width - offset.right; x++) {
110+
newContext.putImageData(imageData, x, newCanvas.height - offset.bottom);
111+
}
112+
}
113+
114+
// scale middle left
115+
rootX = 1; rootY = offset.top;
116+
if(offset.left - 1 > 0) {
117+
imageData = context.getImageData(rootX, rootY, offset.left - 1, 1);
118+
for(let y = offset.top - 1; y <= newCanvas.height - offset.top; y++) {
119+
newContext.putImageData(imageData, 0, y);
120+
}
121+
}
122+
123+
// scale middle right
124+
rootX = canvas.width - offset.right; rootY = offset.top;
125+
if(offset.right - 1 > 0) {
126+
imageData = context.getImageData(rootX, rootY, offset.right - 1, 1);
127+
for(let y = offset.top - 1; y <= newCanvas.height - offset.top; y++) {
128+
newContext.putImageData(imageData, newCanvas.width - offset.right, y);
129+
}
130+
}
131+
132+
// scale center
133+
rootX = offset.left; rootY = offset.top;
134+
imageData = context.getImageData(rootX, rootY, 1, 1);
135+
for(let y = offset.top - 1; y <= newCanvas.height - offset.bottom; y++) {
136+
newContext.putImageData(imageData, offset.left - 1, y);
137+
}
138+
imageData = newContext.getImageData(offset.left - 1, offset.top - 1, 1, newCanvas.height - offset.bottom - offset.top);
139+
for(let x = offset.left; x <= newCanvas.width - offset.right; x++) {
140+
newContext.putImageData(imageData, x, offset.top -1);
141+
}
142+
143+
var dataUrl = newCanvas.toDataURL();
144+
resolve({url: dataUrl, width: self.newWidth, height: self.newHeight});
145+
};
146+
image.onerror = function(error) {
147+
reject(error);
148+
}
149+
image.src = srcImg;
150+
});
151+
}
152+
153+
function getOffsetFromCanvas(canvas, context) {
154+
var offset = {
155+
top: 0,
156+
bottom: 0,
157+
left: 0,
158+
right: 0
159+
}
160+
// Get top offset
161+
for(let y = 0; y < canvas.height; y++) {
162+
var p = context.getImageData(0, y, 1, 1).data;
163+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.top++;
164+
else break;
165+
}
166+
// Get bottom offset
167+
for(let y = canvas.height - 1; y >= 0; y--) {
168+
var p = context.getImageData(0, y, 1, 1).data;
169+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.bottom++;
170+
else break;
171+
}
172+
// Get left offset
173+
for(let x = 0; x < canvas.width; x++) {
174+
var p = context.getImageData(x, 0, 1, 1).data;
175+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.left++;
176+
else break;
177+
}
178+
// Get right offset
179+
for(let x = canvas.width - 1; x >= 0; x--) {
180+
var p = context.getImageData(x, 0, 1, 1).data;
181+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.right++;
182+
else break;
183+
}
184+
return offset;
185+
}
186+
187+
function isTransparent(rgbArray) {
188+
return (rgbArray[0] == 0 && rgbArray[1] == 0 && rgbArray[2] == 0 && rgbArray[3] == 0);
189+
}
190+
191+
function getOffset(srcImg) {
192+
return new Promise(function(resolve, reject){
193+
var offset = {top: 0, right: 0, bottom: 0, left: 0}
194+
var canvas = document.createElement('canvas');
195+
var context = canvas.getContext('2d');
196+
var image = new Image();
197+
198+
image.onload = function() {
199+
canvas.width = image.width;
200+
canvas.height = image.height;
201+
context.drawImage(image, 0, 0, image.width, image.height);
202+
203+
// Get top offset
204+
for(let y = 0; y < canvas.height; y++) {
205+
var p = context.getImageData(0, y, 1, 1).data;
206+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.top++;
207+
else break;
208+
}
209+
// Get bottom offset
210+
for(let y = canvas.height - 1; y >= 0; y--) {
211+
var p = context.getImageData(0, y, 1, 1).data;
212+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.bottom++;
213+
else break;
214+
}
215+
// Get left offset
216+
for(let x = 0; x < canvas.width; x++) {
217+
var p = context.getImageData(x, 0, 1, 1).data;
218+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.left++;
219+
else break;
220+
}
221+
// Get right offset
222+
for(let x = canvas.width - 1; x >= 0; x--) {
223+
var p = context.getImageData(x, 0, 1, 1).data;
224+
if(isTransparent([p[0], p[1], p[2], p[3]])) offset.right++;
225+
else break;
226+
}
227+
resolve(offset);
228+
};
229+
image.onerror = function(error) {
230+
reject(error);
231+
}
232+
image.src = srcImg;
233+
});
234+
}
235+
window.NinePatch = NinePatch;
236+
})(document, window);

0 commit comments

Comments
 (0)