KonvaJS - сделать его отзывчивым с помощью Bootstrap Modals - PullRequest
0 голосов
/ 15 октября 2018

Ниже представлен проект KonvaJS, в котором вы можете добавить наклейки к изображению.Тем не менее, он имеет фиксированную ширину и фиксированную высоту.

Теперь, поскольку размеры фиксированы, он не будет работать ни с каким ответом, как с модальностью начальной загрузки.

Вот моя попытка следовать руководству по ответам KonvaJS, см. Здесь. и руководство здесь.

В моей попытке после загрузкиизображение, мой код не может получить новую ширину модального, так как он возвращает 0, поэтому он не может рассчитать его для размера холста.

Как я могу сделать отзывчивым холст?

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>

Итак, позвольте мне попытаться объяснить проблему немного подробнее: Проверьте живую версию моей попытки сделать ее отзывчивой.

enter image description here

Как вы можете видеть, после попытки загрузить изображение на холст, модал всплывает, но холст не может изменить размер.

Вот 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();
}

1 Ответ

0 голосов
/ 17 октября 2018

Техника, которую вы использовали для прослушивания «изменения размера» на странице, будет работать для главного окна, но, вероятно, не для модального.Вы можете подтвердить это с помощью простого вывода console.log ().

Вам нужно использовать событие начальной загрузки на ('show.bs.modal'), чтобы перехватить, когда показывается модальное состояние, то есть когда вы действительно хотите запустить вызов fitStageIntoParentContainer ();

См. этот ТАК пост для информации .Он не является дубликатом, но охватывает модальное событие начальной загрузки.

В случае, если этот вопрос удален, вы должны отправиться к чему-то вроде:

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