Cropper JS:Bootstrap模式中的定位/大小问题

问题描述 投票:1回答:2

enter image description here

这是输出屏幕,其中图像没有正确定位,大小在引导模式内。

我试图在我的项目的'avatar'更新部分使用'cropper.js'插件。我还使用jquery添加了相关的CSS和JS文件,插件工作正常。我的问题是引导模态内的图像定位/大小。它显示在小和左中间。我正在尝试使它们尺寸合适,定位和响应输出。我试过的是在下面添加。对这个问题的任何帮助都非常感谢。

我做了什么:

main.js文件,用于使用cropper插件初始化/上传和裁剪图像

(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as anonymous module.
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // Node / CommonJS
    factory(require('jquery'));
  } else {
    // Browser globals.
    factory(jQuery);
  }
})(function ($) {

  'use strict';

  var console = window.console || { log: function () {} };

  function CropAvatar($element) {
    this.$container = $element;

    this.$avatarView = this.$container.find('.avatar-view');
    this.$avatar = this.$avatarView.find('img');
    this.$avatarModal = this.$container.find('#avatar-modal');
    this.$avatarModal1 = this.$container.find('#avatar-modal1');
    this.$loading = this.$container.find('.loading');

    this.$avatarForm = this.$avatarModal1.find('.avatar-form');
    this.$avatarUpload = this.$avatarForm.find('.avatar-upload');
    this.$avatarSrc = this.$avatarForm.find('.avatar-src');
    this.$avatarData = this.$avatarForm.find('.avatar-data');
    this.$avatarInput = this.$avatarForm.find('.avatar-input');
    this.$avatarSave = this.$avatarForm.find('.avatar-save');
    this.$avatarBtns = this.$avatarForm.find('.avatar-btns');

    this.$avatarWrapper = this.$avatarModal.find('.avatar-wrapper');
    this.$avatarPreview = this.$avatarModal.find('.avatar-preview');

    this.init();
  }

  CropAvatar.prototype = {
    constructor: CropAvatar,

    support: {
      fileList: !!$('<input type="file">').prop('files'),
      blobURLs: !!window.URL && URL.createObjectURL,
      formData: !!window.FormData
    },

    init: function () {
      this.support.datauri = this.support.fileList && this.support.blobURLs;

      if (!this.support.formData) {
        this.initIframe();
      }

      this.initTooltip();
      this.initModal();
      this.addListener();
    },

    addListener: function () {
      this.$avatarView.on('click', $.proxy(this.click, this));

      this.$avatarInput.on('change', $.proxy(this.change, this));
      //this.$avatarInput.on('change', $.proxy(this.click, this));

      this.$avatarForm.on('submit', $.proxy(this.submit, this));
      this.$avatarBtns.on('click', $.proxy(this.rotate, this));
    },

    initTooltip: function () {
      this.$avatarView.tooltip({
        placement: 'bottom'
      });
    },


    initPreview: function () {
      var url = this.$avatar.attr('src');

      this.$avatarPreview.html('<img src="' + url + '">');
    },

    initIframe: function () {
      var target = 'upload-iframe-' + (new Date()).getTime();
      var $iframe = $('<iframe>').attr({
            name: target,
            src: ''
          });
      var _this = this;

      // Ready ifrmae
      $iframe.one('load', function () {

        // respond response
        $iframe.on('load', function () {
          var data;

          try {
            data = $(this).contents().find('body').text();
          } catch (e) {
            console.log(e.message);
          }

          if (data) {
            try {
              data = $.parseJSON(data);
            } catch (e) {
              console.log(e.message);
            }

            _this.submitDone(data);
          } else {
            _this.submitFail('Image upload failed!');
          }

          _this.submitEnd();


        });
      });

      this.$iframe = $iframe;
      this.$avatarForm.attr('target', target).after($iframe.hide());
    },
     initModal: function () {
      this.$avatarModal.modal({
        show: false
      });
    },


    click: function () {
      this.$avatarModal.modal('show');
      this.initPreview();
    },
    change: function () {
      //alert("changed");
      this.$avatarModal.modal('show');
             this.initPreview();

      var files;
      var file;

      if (this.support.datauri) {
        files = this.$avatarInput.prop('files');

        if (files.length > 0) {
          file = files[0];

          if (this.isImageFile(file)) {
            if (this.url) {
              URL.revokeObjectURL(this.url); // Revoke the old one
            }



            this.url = URL.createObjectURL(file);
            this.startCropper();

          }
        }
      } else {
        file = this.$avatarInput.val();

        if (this.isImageFile(file)) {
          //alert("changed");
          this.syncUpload();
        }
      }
    },


    isImageFile: function (file) {
      if (file.type) {
        return /^image\/\w+$/.test(file.type);
      } else {
        return /\.(jpg|jpeg|png|gif)$/.test(file);
      }
    },

    startCropper: function () {
      var _this = this;

      if (this.active) {
        this.$img.cropper('replace', this.url);
      } else {
        this.$img = $('<img src="' + this.url + '">');
        this.$avatarWrapper.empty().html(this.$img);
        this.$img.cropper({
          //aspectRatio: 1,
          aspectRatio: 1,
          preview: this.$avatarPreview.selector,
          crop: function (e) {
            var json = [
                  '{"x":' + e.x,
                  '"y":' + e.y,
                  '"height":' + e.height,
                  '"width":' + e.width,
                  '"rotate":' + e.rotate + '}'
                ].join();

            _this.$avatarData.val(json);
             $("#output").html("("+e.width+","+e.height+")");
          }
        });

      this.active = true;
      }

      this.$avatarModal.one('hidden.bs.modal', function () {
        _this.$avatarPreview.empty();
        _this.stopCropper();
      });
    },

    stopCropper: function () {
      if (this.active) {
        this.$img.cropper('destroy');
        this.$img.remove();
        this.active = false;
      }
    },

    syncUpload: function () {
      this.$avatarSave.click();
    },

    alert: function (msg) {
      var $alert = [
            '<div class="alert alert-danger avatar-alert alert-dismissable">',
              '<button type="button" class="close" data-dismiss="alert">&times;</button>',
              msg,
            '</div>'
          ].join('');

      this.$avatarUpload.after($alert);
    }
  };

  $(function () {
    return new CropAvatar($('#crop-avatar'));
  });

}); 

主页 - HTML视图页面

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Image Cropping with Cropper JS</title>
  <link rel="stylesheet" href="css/bootstrap.min.css">
  <link rel="stylesheet" href="css/cropper.min.css">
  <link rel="stylesheet" href="css/cropper.css">
  <link rel="stylesheet" href="css/styles.css">

</head>
<body>
  <div class="container" id="crop-avatar">

    <!-- Current avatar -->
    <div class="avatar-view" title="Change the avatar">
      <img src="img/img.jpg" alt="Avatar">
    </div>

    <div id="avatar-modal1">
    <form class="avatar-form" action="crop.php" enctype="multipart/form-data" method="post">

      <!-- Upload image and data -->
                <div class="avatar-upload">
                  <input type="hidden" class="avatar-src" name="avatar_src">
                  <input type="hidden" class="avatar-data" name="avatar_data">
                  <label for="avatarInput">Upload</label>
                  <input type="file" class="avatar-input" id="avatarInput" name="avatar_file">
                </div>
    <!-- Cropping modal -->
    <div class="modal fade" id="avatar-modal" aria-hidden="true" aria-labelledby="avatar-modal-label" role="dialog" tabindex="-1">
      <div class="modal-dialog modal-lg">
        <div class="modal-content">

            <div class="modal-header">
              <button type="button" class="close" data-dismiss="modal">&times;</button>
              <h4 class="modal-title" id="avatar-modal-label">Change Image</h4>
            </div>
            <div class="modal-body">
              <div class="avatar-body">



                <!-- Crop and preview -->
                <div class="row">
                  <div class="col-md-9">
                    <div class="avatar-wrapper"> </div>
                  </div>
                  <div class="col-md-3">
                    <div class="avatar-preview preview-lg" style="border-radius:90px !important;"></div>
                    <!-- <div class="avatar-preview preview-md"></div>
                    <div class="avatar-preview preview-sm"></div>-->
                    <br>
                    <h5>Output value(width,height)</h5>
                    <div id="output"></div>



                  </div>
                </div>

                <div class="row avatar-btns">
                  <!--<div class="col-md-9">
                    <div class="btn-group">
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="-90" title="Rotate -90 degrees">Rotate Left</button>
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="-15">-15deg</button>
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="-30">-30deg</button>
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="-45">-45deg</button>
                    </div>
                    <div class="btn-group">
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="90" title="Rotate 90 degrees">Rotate Right</button>
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="15">15deg</button>
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="30">30deg</button>
                      <button type="button" class="btn btn-primary" data-method="rotate" data-option="45">45deg</button>
                    </div>
                  </div>
                  <div class="col-md-3">
                    <button type="submit" class="btn btn-primary btn-block avatar-save">Done</button>
                  </div>-->
                </div>
              </div>
            </div>

        </div>
      </div>
    </div><!-- /.modal -->

  </form>
  </div>
    <!-- Loading state -->
     <div class="loading" aria-label="Loading" role="img" tabindex="-1"></div>
  </div>

  <script src="js/jquery.min.js"></script>
  <script src="js/bootstrap.min.js"></script>
  <script src="js/cropper.min.js"></script>
  <script src="js/main.js"></script>
</body>
</html>
jquery html twitter-bootstrap jquery-plugins cropperjs
2个回答
0
投票

我找出了问题,

问题

我们初始化时,Bootstrap模态内容(CSS和元素)没有完全加载

(1)。在使用bootstrap-modal事件方法加载事件之后,首先准备好Bootstrap模态内容。

(2)。根据使用情况使用延迟或删除延迟


0
投票

请查看以下来自https://github.com/fengyuanchen/cropperjs#notes的说明

笔记

  1. 裁剪器的大小继承自图像的父元素(包装器)的大小,因此请务必使用可见的块元素包装图像。 如果在模态中使用裁剪器,则应在完全显示模态后初始化裁剪器。否则,您将无法获得正确的裁剪器。
  2. 输出的裁剪数据基于原始图像大小,因此您可以使用它们直接裁剪图像。
  3. 如果您尝试在跨源图像上启动裁剪器,请确保您的浏览器支持HTML5 CORS设置属性,并且您的图像服务器支持Access-Control-Allow-Origin选项(请参阅HTTP访问控制(CORS))。
© www.soinside.com 2019 - 2024. All rights reserved.