简体   繁体   English

KonvaJS-使用Bootstrap Modals做出响应

[英]KonvaJS - Making it responsive with Bootstrap Modals

Below is a KonvaJS project where you can add stickers to an image. 以下是KonvaJS项目,您可以在其中向图像添加贴纸。 However, it has a fixed width and a fixed height. 但是,它具有固定的宽度和固定的高度。

Now because the sizes are fixed, it won't work with anything response, like a bootstrap modal. 现在,由于大小是固定的,因此它无法响应任何响应,例如引导程序模态。

Here is my attempt following a KonvaJS response guide, see here. 这是我遵循KonvaJS响应指南的尝试, 请参见此处。 and the guide here. 还有这里指南。

In my attempt, after I upload the image, my code can't get the new width of the modal as it returns 0, so it can't calculate it for the size of the canvas. 在尝试上传图像后,我的代码无法获得模态的新宽度,因为它返回0,因此无法针对画布的大小进行计算。

How can I make the canvas responsive? 如何使画布响应?

 function centreRectShape(shape) { shape.x((stage.getWidth() - shape.getWidth()) / 2); shape.y((stage.getHeight() - shape.getHeight()) / 2); } var stage = new Konva.Stage({ container: 'canvas-container', width: 650, height: 300 }); var layer = new Konva.Layer(); stage.add(layer); var bgRect = new Konva.Rect({ width: stage.getWidth(), height: stage.getHeight(), fill: 'gold', opacity: 0.1 }); layer.add(bgRect); var uploadedImage = new Konva.Image({ draggable: false }); layer.add(uploadedImage); // make an object to keep things tidy - not strictly needed, just being tidy function addSticker(imgUrl){ // make the sticker image object var stickerObj = new Konva.Image({ x: 240, y: 20, width: 93, height: 104, name: 'sticker', draggable: true }); layer.add(stickerObj); // make the sticker image loader html element var stickerImage = new Image(); stickerImage.onload = function() { stickerObj.image(stickerImage); layer.draw(); }; stickerObj.on('transformstart', function(){ undoBefore = makeUndo(this); }) stickerObj.on('transformend', function(){ var undoAfter = makeUndo(this); addUndo(123, undoBefore, undoAfter) }) // assigning the URL of the image starts the onload stickerImage.src = imgUrl; } imgObj = new Image(); imgObj.onload = function() { uploadedImage.image(imgObj); var padding = 20; var w = imgObj.width; var h = imgObj.height; var targetW = stage.getWidth() - (2 * padding); var targetH = stage.getHeight() - (2 * padding); var widthFit = targetW / w; var heightFit = targetH / h; var scale = (widthFit > heightFit) ? heightFit : widthFit; w = parseInt(w * scale, 10); h = parseInt(h * scale, 10); uploadedImage.size({ width: w, height: h }); centreRectShape(uploadedImage); layer.draw(); } imgObj.src = 'https://images.pexels.com/photos/787961/pexels-photo-787961.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260'; $('.sticker').on('click', function() { var theSticker = addSticker($(this).attr('src')); toggle(true); toggle(false); }); var vis = false; $('#toggler').on('click', function(){ toggle(vis); }) function undoData(opts){ this.x = opts.x; this.y = opts.y; this.width = opts.w; this.height = opts.h; this.rotation = opts.r; } var undoBefore; function makeUndo(shape){ return new undoData({x:shape.getX(), y: shape.getY(), w: shape.getWidth(), h: shape.getHeight(), r: shape.getRotation() }) } var undoList = []; function addUndo(shapeId, before, after){ undoList.push({id: shapeId, before: before, after: after}); console.log(undoList[undoList.length - 1]) } function toggle(isVisible){ if (!isVisible){ var shapes = stage.find('.sticker'); shapes.each(function(shape) { var imgRotator = new Konva.Transformer({ node: shape, name: 'stickerTransformer', keepRatio: true, enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'] }); layer.add(imgRotator); }) vis = true; } else { var shapes = stage.find('.stickerTransformer'); shapes.each(function(shape) { shape.remove(); }) vis=false; } layer.draw(); $('#toggler').html((vis ? 'Toggle Off' : 'Toggle On')); } 
 html, * { margin: 0; padding: 0; } body { background: #eee; } #image-editor { background: #fff; border-radius: 3px; border: 1px solid #d8d8d8; width: 650px; margin: 0 auto; margin-top: 20px; box-shadow: 0 3px 5px rgba(0, 0, 0, .2); } .stickers { padding: 10px 5px; background: #eee; } .stickers>img { margin-right: 10px; } 
  <div id="image-editor"> <div id="canvas-container"></div> <div class="stickers"> <img class="sticker" src="https://craftblock.me/koa/fb-upload-clone/stickers/sticker%20(1).png" alt="Sticker" width="62px"> </div> </div> <script src="https://unpkg.com/konva@2.4.1/konva.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

So let me try to explain the issue a bit more: Check out the live version of my attempt of making it responsive. 因此,让我尝试进一步解释该问题: 看看我使它响应的尝试的实时版本。

在此处输入图片说明

As you can see, after trying to load the image into the canvas, the modal pops up but the canvas fails to resize. 如您所见,在尝试将图像加载到画布中之后,弹出了模态,但是画布无法调整大小。

Here's the JS to that: 这是JS:

    /**
 * Image Editor
 */

var stageWidth = 1000;
var stageHeight = 1000;

var stage = new Konva.Stage({
    container: 'canvas-container',
    width: stageWidth,
    height: stageHeight
});

var layer = new Konva.Layer();
stage.add(layer);

var bgRect = new Konva.Rect({
    width: stage.getWidth(),
    height: stage.getHeight(),
    fill: 'gold',
    opacity: 0.1
});
layer.add(bgRect);

var uploadedImage = new Konva.Image({
    draggable: false
});

layer.add(uploadedImage);

imgObj.onload = function () {

    uploadedImage.image(imgObj);

    var padding = 20;
    var w = imgObj.width;
    var h = imgObj.height;

    var targetW = stage.getWidth() - (2 * padding);
    var targetH = stage.getHeight() - (2 * padding);

    var widthFit = targetW / w;
    var heightFit = targetH / h;
    var scale = (widthFit > heightFit) ? heightFit : widthFit;

    w = parseInt(w * scale, 10);
    h = parseInt(h * scale, 10);

    uploadedImage.size({
        width: w,
        height: h
    });
    centreRectShape(uploadedImage);
    layer.draw();
}

$('.sticker').on('click', function () {
    addSticker($(this).attr('src'));
});

fitStageIntoParentContainer();
window.addEventListener('resize', fitStageIntoParentContainer);

function centreRectShape(shape) {
    shape.x((stage.getWidth() - shape.getWidth()) / 2);
    shape.y((stage.getHeight() - shape.getHeight()) / 2);
}

function addSticker(imgUrl) {
    var stickerObj = new Konva.Image({
        x: 240,
        y: 20,
        width: 93,
        height: 104,
        draggable: true
    });
    var stickerImage = new Image();
    stickerImage.onload = function () {
        stickerObj.image(stickerImage);
        centreRectShape(stickerObj);
        layer.draw();
    };
    stickerImage.src = imgUrl;
    layer.add(stickerObj);
    addModifiers(stickerObj);
}

function addModifiers(obj) {
    var imgRotator = new Konva.Transformer({
        node: obj,
        keepRatio: true,
        enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
    });
    layer.add(imgRotator);
}

function fitStageIntoParentContainer() {
    var container = document.querySelector("edit-image-modal");

    // now we need to fit stage into parent
    var containerWidth = container.offsetWidth;
    // to do this we need to scale the stage
    var scale = containerWidth / stageWidth;


    stage.width(stageWidth * scale);
    stage.height(stageHeight * scale);
    stage.scale({
        x: scale,
        y: scale
    });
    stage.draw();
}

The technique you have used to listen for 'resize' on the page will work for the main window but likely not for the modal. 您用来侦听页面上“调整大小”的技术将适用于主窗口,但不适用于模式。 You can confirm that by some simple console.log() output. 您可以通过一些简单的console.log()输出来确认。

You need to use the bootstrap event on('show.bs.modal') to catch when the modal is shown, which is when you really want to fire the call to fitStageIntoParentContainer(); 您需要使用bootstrap事件on('show.bs.modal')捕获显示模态的时间,即您确实要触发对fitStageIntoParentContainer()的调用时;

See this SO post for info . 有关信息,请参见此SO帖子 It is not a duplicate but covers the bootstrap modal event. 它不是重复项,而是涵盖了引导程序模式事件。

In case that question is erased, you should be heading for something like: 万一这个问题被消除,您应该朝着类似的方向前进:

$('your_modal_element_selector').on('show.bs.modal', function () {
       fitStageIntoParentContainer();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM