картинка масштабируется

main
parent 8e53b56482
commit 84ab8fc59f

BIN
1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

@ -0,0 +1,12 @@
/*!
* imagesLoaded PACKAGED v5.0.0
* JavaScript is all like "You images are done yet or what?"
* MIT License
*/
!function(t,e){"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,(function(){function t(){}let e=t.prototype;return e.on=function(t,e){if(!t||!e)return this;let i=this._events=this._events||{},s=i[t]=i[t]||[];return s.includes(e)||s.push(e),this},e.once=function(t,e){if(!t||!e)return this;this.on(t,e);let i=this._onceEvents=this._onceEvents||{};return(i[t]=i[t]||{})[e]=!0,this},e.off=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;let s=i.indexOf(e);return-1!=s&&i.splice(s,1),this},e.emitEvent=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;i=i.slice(0),e=e||[];let s=this._onceEvents&&this._onceEvents[t];for(let n of i){s&&s[n]&&(this.off(t,n),delete s[n]),n.apply(this,e)}return this},e.allOff=function(){return delete this._events,delete this._onceEvents,this},t})),
/*!
* imagesLoaded v5.0.0
* JavaScript is all like "You images are done yet or what?"
* MIT License
*/
function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}("undefined"!=typeof window?window:this,(function(t,e){let i=t.jQuery,s=t.console;function n(t,e,o){if(!(this instanceof n))return new n(t,e,o);let r=t;var h;("string"==typeof t&&(r=document.querySelectorAll(t)),r)?(this.elements=(h=r,Array.isArray(h)?h:"object"==typeof h&&"number"==typeof h.length?[...h]:[h]),this.options={},"function"==typeof e?o=e:Object.assign(this.options,e),o&&this.on("always",o),this.getImages(),i&&(this.jqDeferred=new i.Deferred),setTimeout(this.check.bind(this))):s.error(`Bad element for imagesLoaded ${r||t}`)}n.prototype=Object.create(e.prototype),n.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)};const o=[1,9,11];n.prototype.addElementImages=function(t){"IMG"===t.nodeName&&this.addImage(t),!0===this.options.background&&this.addElementBackgroundImages(t);let{nodeType:e}=t;if(!e||!o.includes(e))return;let i=t.querySelectorAll("img");for(let t of i)this.addImage(t);if("string"==typeof this.options.background){let e=t.querySelectorAll(this.options.background);for(let t of e)this.addElementBackgroundImages(t)}};const r=/url\((['"])?(.*?)\1\)/gi;function h(t){this.img=t}function d(t,e){this.url=t,this.element=e,this.img=new Image}return n.prototype.addElementBackgroundImages=function(t){let e=getComputedStyle(t);if(!e)return;let i=r.exec(e.backgroundImage);for(;null!==i;){let s=i&&i[2];s&&this.addBackground(s,t),i=r.exec(e.backgroundImage)}},n.prototype.addImage=function(t){let e=new h(t);this.images.push(e)},n.prototype.addBackground=function(t,e){let i=new d(t,e);this.images.push(i)},n.prototype.check=function(){if(this.progressedCount=0,this.hasAnyBroken=!1,!this.images.length)return void this.complete();let t=(t,e,i)=>{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n}));

@ -0,0 +1,48 @@
// konva-utils.js
export function attachStageResizer(root, stage) {
const observer = new ResizeObserver(() => {
if (!stage) return;
stage.width(root.clientWidth);
stage.height(root.clientHeight);
stage.batchDraw();
});
observer.observe(root);
return observer;
}
// масштабирует картинку по stage
export function fitImageToStage(konvaImage, stage) {
const img = konvaImage.image();
const sw = stage.width();
const sh = stage.height();
const iw = img.naturalWidth;
const ih = img.naturalHeight;
const scale = Math.min(sw / iw, sh / ih);
konvaImage.width(iw);
konvaImage.height(ih);
konvaImage.scale({ x: scale, y: scale });
// центрируем
konvaImage.x((sw - iw * scale) / 2);
konvaImage.y((sh - ih * scale) / 2);
}
export function coverImageToStage(konvaImage, stage) {
const img = konvaImage.image();
const sw = stage.width();
const sh = stage.height();
const iw = img.naturalWidth;
const ih = img.naturalHeight;
const scale = Math.max(sw / iw, sh / ih);
konvaImage.width(iw);
konvaImage.height(ih);
konvaImage.scale({ x: scale, y: scale });
// центрируем и обрезаем по центру
konvaImage.x((sw - iw * scale) / 2);
konvaImage.y((sh - ih * scale) / 2);
}

@ -1,3 +1,7 @@
# konva-editor
nue2 + konva
nue2 + konva
## Особенности
- вынес часть кода из компонента в отдельный файл.
- 23.12.2025 - картинка загружается, пока бех масштабироваания

@ -1,5 +1,13 @@
<!dhtml lib>
<script>
import {
attachStageResizer,
fitImageToStage,
coverImageToStage,
} from "./@shared/konva-utils.js"
</script>
<konva-editor>
<script>
this.stage = null;
@ -7,7 +15,7 @@
mounted() {
const width = this.root.clientWidth || 500;
const height = this.root.clientHeight || 500;
const height = this.root.clientHeight || 400;
this.stage = new Konva.Stage({
container: this.root,
@ -15,17 +23,25 @@
height,
});
this._resizeObserver = new ResizeObserver(() => {
if (!this.stage) return;
this.layer = new Konva.Layer();
this.stage.add(this.layer);
this.stage.width(this.root.clientWidth);
this.stage.height(this.root.clientHeight);
this.stage.batchDraw();
});
this._resizeObserver = attachStageResizer(this.root, this.stage);
this.addImage("1.jpg");
this._resizeObserver.observe(this.root);
}
// простой метод добавления картинки через Konva
addImage(url) {
// опционально: добавить crossOrigin, если нужно
Konva.Image.fromURL(url, (konvaImage) => {
coverImageToStage(konvaImage, this.stage); // масштабирование (fit?)
konvaImage.setAttrs({ x: 0, y: 0, draggable: true, });
this.layer.add(konvaImage);
this.layer.draw();
}, { crossOrigin: 'Anonymous' });
};
unmounted() {
this._resizeObserver?.disconnect();
this._resizeObserver = null;

Loading…
Cancel
Save