js 某宽高(img)以相等的比例缩放至规定的大小

 

废话在后文讲, 具体的 javascript 实现代码:

 1 /* 把 target 以相等的比例缩放至 result 大小
 2     target, result: Object{width, height}; //也可以是img元素
 3 */
 4 setSizeToSameScale(target, result = {width: 100, height: 100}){
 5     if(!target) return result;
 6 
 7     const width = target.width, 
 8     height = target.height,
 9     ratio = width / height,
10     scale = ratio < 1 ? ratio * result.width / width : result.width / width;
11 
12     result.width = width * scale;
13     result.height = height * scale;
14     
15     return result;
16 }

 

思路:

  根据  targetresult 的宽高比计算出 scale

  然后 result 的宽高乘以这个 scale 就ok了

 

 

这里我用此方法处理某些功能: (空降至 234 行 的

setScaleToSameScaleFromBox 方法

)

这个类不能直接使用, 只当做示例

  1 /* CanvasImage 
  2 parameter: 
  3     image (构造器会调用一次 .setImage(image) 来处理 image 参数)
  4 
  5 attribute:
  6     opacity: Float;     //透明度; 值0至1之间; 默认1;
  7     visible: Boolean;    //默认true; 完全隐藏(既不绘制视图, 也不触发绑定的事件)
  8     box: Box;             //.x.y 图像的位置, .w.h 图像的宽高;
  9     rotate: Roate;        //旋转; 默认 null (注意: 旋转的原点是相对于 box.x.y 的)
 10     scale: Box;            //缩放; .x.y中心点, .w.h缩放; 默认 null; (注意: 缩放的原点是相对于 box.x.y 的)
 11     x, y: Number;        //this.box 的 .x.y
 12 
 13     //以下属性不建议直接修改
 14     overlap: Object; //CanvasImageRender.computeOverlaps(ca) 方法更新
 15     index: Integer; //CanvasImageRender.index(ca) 修改
 16 
 17     //只读
 18     width, height, image; isRotate, isScale
 19 
 20 method:
 21     setImage(image): this;         //设置图像 (image 如果是 CanvasImage 并它正在加载图像时, 则会在它加载完成时自动设置 image);
 22     load(src, onload): this;    //加载并设置图像 (onload 如果是 CanvasImageRender 则加载完后自动调用一次 redraw 或 render 方法);
 23     pos(x, y): this;             //设置位置; x 可以是: Number, Object{x,y}
 24     
 25     //以nx,ny为原点缩放; ratio 小于1为缩, 大于1是放
 26     setScale(nx = 0, ny = 0, ratio = 1): this; 
 27 
 28     //设置 this.scale 的宽为 newWidth, 
 29     //然后以 this.image 的相等比例缩放至 newWidth; 
 30     //newWidth 默认为 this.box 的宽
 31     setScaleToSameScaleFromBox(newWidth): this; 
 32 
 33     //设置 this.scale 的位置在 this.box 中居中
 34     setScaleToCenterFromBox(): this;
 35 
 36 demo:
 37     //CanvasImageRender
 38     const cir = new CanvasImageRender({width: WORLD.width, height: WORLD.height});
 39     cir.domElement.style = `
 40         position: absolute;
 41         z-index: 9999;
 42         background: rgb(127,127,127);
 43     `;
 44 
 45     //values
 46     const ciA = cir.add(new CanvasImage()).pos(59, 59).load("view/examples/img/test.png", cir);
 47     ciA.opacity = 0.2; //设置透明度
 48 
 49     const ciB = cir.add(new CanvasImage(ciA)).pos(59, 120);
 50     ciB.rotate = new Rotate().toAngle(45); //旋转45度
 51 
 52     //event
 53     const cie = new CanvasImageEvent(cir); //注意: CanvasImage 的缩放和旋转都会影响到 CanvasImageEvent
 54     cie.add(ciB, "click", event => { //ciB 添加 点击事件
 55         console.log("click ciB: ", event);
 56     });
 57 */
 58 class CanvasImage{
 59 
 60     static bindBox(obj, box){
 61         var _x = box.x, _y = box.y, _w = box.w, _h = box.h, oldV;
 62 
 63         Object.defineProperties(box, {
 64 
 65             x: {
 66                 get: () => {return _x;},
 67                 set: v => {
 68                     oldV = _x;
 69                     _x = v;
 70                     if(obj.writeBoxX !== null) obj.writeBoxX(v+_w, oldV+_w);
 71                 }
 72             },
 73 
 74             y: {
 75                 get: () => {return _y;},
 76                 set: v => {
 77                     oldV = _y;
 78                     _y = v;
 79                     if(obj.writeBoxY !== null) obj.writeBoxY(v+_h, oldV+_h);
 80                 }
 81             },
 82 
 83             w: {
 84                 get: () => {return _w;},
 85                 set: v => {
 86                     oldV = _w;
 87                     _w = v;
 88                     if(obj.writeBoxX !== null) obj.writeBoxX(v+_x, oldV+_x);
 89                 }
 90             },
 91 
 92             h: {
 93                 get: () => {return _h;},
 94                 set: v => {
 95                     oldV = _h;
 96                     _h = v;
 97                     if(obj.writeBoxY !== null) obj.writeBoxY(v+_y, oldV+_y);
 98                 }
 99             },
100 
101         });
102     }
103 
104     #box = new Box();
105     #image = null;
106     #isLoadImage = false;
107     #__bindObj = {
108         writeBoxX: null,
109         writeBoxY: null,
110     }
111 
112     get box(){return this.#box;}
113     get image(){return this.#image;}
114     get isScale(){return this.#image.width !== this.box.w || this.#image.height !== this.box.h;}
115     get width(){return this.#image !== null ? this.#image.width : 0;}
116     get height(){return this.#image !== null ? this.#image.height : 0;}
117     get isLoadImage(){return this.#isLoadImage;}
118     get __bindObj(){return this.#__bindObj;}
119 
120     get x(){return this.box.x;}
121     get y(){return this.box.y;}
122     set x(v){this.box.x = v;}
123     set y(v){this.box.y = v;}
124     
125     constructor(image){
126         this.opacity = 1;
127         this.visible = true;
128         this.rotate = null;
129         this.scale = null;
130 
131         //以下属性不建议直接修改
132         this.overlap = null;
133         this.index = -1;
134 
135         CanvasImage.bindBox(this.#__bindObj, this.#box);
136         this.setImage(image);
137     }
138 
139     pos(x, y){
140         if(UTILS.isNumber(x)){
141             this.box.x = x;
142             this.box.y = y;
143         }
144         else if(UTILS.isObject(x)){
145             this.box.x = x.x;
146             this.box.y = x.y;
147         }
148         return this;
149     }
150 
151     setImage(image){
152         if(CanvasImageRender.isCanvasImage(image)){
153             this.box.size(image.width, image.height);
154             this.#image = image;
155         }
156         else if(CanvasImage.prototype.isPrototypeOf(image)){
157             if(image.isLoadImage){
158                 if(Array.isArray(image.loadImage_cis)) image.loadImage_cis.push(this);
159                 else image.loadImage_cis = [this];
160             }
161             else this.setImage(image.image);
162         }
163         else{
164             this.box.size(0, 0);
165             this.#image = null;
166         }
167         return this;
168     }
169 
170     loadImage(src, onload){
171         this.#isLoadImage = true;
172         const image = new Image();
173         image.onload = () => this._loadSuccess(image, onload);
174         image.src = src;
175         return this;
176     }
177 
178     loadVideo(src, onload, type = "mp4"){
179         /*    video 加载事件 的顺序
180             onloadstart
181             ondurationchange
182             onloadedmetadata //元数据加载完成包含: 时长,尺寸大小(视频),文本轨道。
183             onloadeddata
184             onprogress
185             oncanplay
186             oncanplaythrough
187 
188             //控制事件:
189             onended //播放结束
190             onpause //暂停播放
191             onplay //开始播放
192         */
193         this.#isLoadImage = true;
194         const video = document.createElement("video"),
195         source = document.createElement("source");
196         video.appendChild(source);
197         source.type = `video/${type}`;
198 
199         video.onloadedmetadata = () => {
200             //video 的 width, height 属性如果不设的话永远都是0
201             video.width = video.videoWidth;
202             video.height = video.videoHeight;
203             this._loadSuccess(video, onload);
204         };
205 
206         source.src = src;
207         return this;
208     }
209 
210     _loadSuccess(image, onload){
211         this.setImage(image);
212         this.#isLoadImage = false;
213 
214         if(Array.isArray(this.loadImage_cis)){
215             this.loadImage_cis.forEach(ci => ci.setImage(image));
216             delete this.loadImage_cis;
217         }
218 
219         if(typeof onload === "function") onload(this);
220         else if(CanvasImageRender.prototype.isPrototypeOf(onload)){
221             if(onload.domElement.parentElement !== null) onload.redraw();
222             else onload.render();
223         }
224     }
225 
226     setScale(nx = 0, ny = 0, ratio = 1){
227         this.scale.w = this.#box.w * ratio;
228         this.scale.h = this.#box.h * ratio;
229         this.scale.x = nx - ((nx - this.scale.x) * ratio + this.scale.x) + this.scale.x;
230         this.scale.y = ny - ((ny - this.scale.y) * ratio + this.scale.y) + this.scale.y;
231         return this;
232     }
233 
234     setScaleToSameScaleFromBox(newWidth = this.#box.w){
235         if(this.#image === null || this.scale === null) return this;
236 
237         const width = this.#image.width, 
238         height = this.#image.height,
239         ratio = width / height,
240         scale = ratio < 1 ? ratio * newWidth / width : newWidth / width;
241 
242         this.scale.w = width * scale;
243         this.scale.h = height * scale;
244         
245         return this;
246     }
247 
248     setScaleToCenterFromBox(){
249         if(this.scale === null) return this;
250 
251         this.scale.x = (this.#box.w - this.scale.w) / 2;
252         this.scale.y = (this.#box.h - this.scale.h) / 2;
253 
254         return this;
255     }
256 
257 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 
posted @ 2022-09-09 19:01  鸡儿er  阅读(200)  评论(0编辑  收藏  举报