Fabricjs Textbox在移动捏手势时缩小

时间:2019-01-24 19:58:28

标签: javascript html css events fabricjs

我希望通常在移动设备上使用捏/缩放手势来调整FabricJS文本框的大小。 据我了解,如果您包含“手势包”,FabricJS会默认实现此方法。

一个特殊的问题是,如果您开始手势,则文本框只会缩小并且无法将其调整大小。 您可以以此尺寸进行测试:

https://www.grabstein-steinmetz.de/phone/editor.html

我怀疑这个问题与html meta标签有关。我尝试了不同的版本,有时调整大小的行为是正确的。这些外观非常不一致,所以我无法识别错误。

画布本身位于flex div内。

$(function(){
      $('#sendAlert').hide();   //initial
      $('#deleteSelected').prop('disabled', true);   //initial
      //makes sure that the custom font works
      WebFont.load({
          custom: {
            families: ['PresidentPlain']
          },
          active: fontsLoaded
      });

      var curFont = 'PresidentPlain';
      var curColor = '#000000';
      var canvas = new fabric.Canvas('canvas');
      var imgElement = document.getElementById('image');


      function fontsLoaded(){
        //initial setup of canvas w/img from url as background
        fabric.Image.fromURL('https://www.grabstein-steinmetz.de/images/urnengrabstein%20258-crop-u116972.jpg', function(img) {
          //scale img & canvas: keep image ratio but stay inside container width & height
          var ratio = img.width / img.height;
          var width = $(window).width();
          var height = width * ratio;
          if(height > $(window).height()){
            height = $(window).height();
            width = height / ratio;
          }
          canvas.setWidth(width)
          canvas.setHeight(height);

          canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
            scaleX: canvas.width / img.width,
            scaleY: canvas.height / img.height
          });
        });

        fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (e) {
          //create new textbox with values from legend
          if(canvas.findTarget(e) === undefined){
            var textbox = new fabric.Textbox('', {
              left: canvas.getPointer(e).x,
              top: canvas.getPointer(e).y,
              fontSize: 20,
              fontFamily: curFont,
              fill: curColor,
              borderColor: 'grey',
              cornerColor: '#2E2E2E',
              cornerSize: 6,
              transparentCorners: false,
              lockUniScaling: true
            });
            canvas.add(textbox).setActiveObject(textbox);
            textbox.enterEditing();
          }
        });

        canvas.on("text:editing:exited", function (e) {
          //delete textbox when left empty
          if(e.target.text == ''){
            canvas.remove(e.target);
          }
        });

        canvas.on('selection:created', function (e) {
          $("#deleteSelected").prop('disabled', true);
          updateLegend(e);
        });
        canvas.on('selection:updated', function(e){
          updateLegend(e);
        })
        canvas.on('selection:cleared', function () {
          $("#deleteSelected").prop('disabled', false);
        });

        function updateLegend(e){
          //set legend according to selection values
          if(e.target.fontFamily === "Arial"){
            $('input[name=font][value=Arial]').prop('checked', true);
          }else{
            $('input[name=font][value=PresidentPlain]').prop('checked', true);
          }
          $('.colorpallet > div').each(function(el){
            $(this).removeClass('coloractive');
          })
          if(e.target.fill === "#000000"){
            $('.colorblack').addClass('coloractive');
            curColor = $('.colorblack').attr('curColor');
          }else if(e.target.fill === "#FFFFFF"){
            $('.colorwhite').addClass('coloractive');
            curColor = $('.colorwhite').attr('curColor');
          }else{
            $('.colorbrown').addClass('coloractive');
            curColor = $('.colorbrown').attr('curColor');
          }
        }




        $('#deleteSelected').click(function(){
          //delete selected textboxes in canvas
          var selection = canvas.getActiveObject();
          if(selection){
            if (selection.type === 'activeSelection') {
              selection.forEachObject(function(element) {
                canvas.remove(element);
              });
            }else{
              canvas.remove(selection);
            }
            canvas.discardActiveObject();
            canvas.requestRenderAll();
          }
        });

        /*MODAL*/
        $('#btnDownload').click(function(){
          canvas.discardActiveObject();
              canvas.requestRenderAll();
          $('#canvas').get(0).toBlob(function(blob){
            saveAs(blob, "Grabstein.png");
          })
        });

        $('#sendBtn').click(function(){
          $('#modalBtn').prop('disabled', true);
          $('#canvas').get(0).toBlob(function(blob){
            var fd = new FormData();
            fd.append('img', blob);
            fd.append('name', $('#input_name').val());
            fd.append('email', $('#input_mail').val());
            fd.append('phone', $('#input_phone').val());
            fd.append('description', $('#input_message').val());
            $.ajax({
              type: 'POST',
              url: '../scripts/editormail.php',
              data: fd,
              processData: false,
              contentType: false
            }).done(function(data) {
              $('#modalBtn').prop('disabled', false);
              console.log(data);
              $('#sendAlert').show();
            });
          });
        });

        $('.modal').on('keyup paste', function(){
          //validate form input
          if($('#input_name').val() && $('#input_mail').val() && validateEmail($('#input_mail').val()) && $('#input_message').val() && $('#input_phone').val()){
            $('#sendBtn').prop('disabled', false);
          }else{
            $('#sendBtn').prop('disabled', true);
          }
        })

        /* LEGEND */
        $('input[type=radio][name=font]').change(function(){
          //change current fontfamily & set fontfamily of selected in canvas
          curFont = this.value;
          var selection = canvas.getActiveObject();
          if(selection){
            if (selection.type === 'activeSelection') {
              selection.forEachObject(function(element) {
                element.set('fontFamily', curFont);
              });
            }else{
              selection.set('fontFamily', curFont);
            }
            canvas.requestRenderAll();
          }
        })

        $('.colorpallet > div').click(function(){
          //change current fontcolor & set fontcolor of selected in canvas
          $('.colorpallet > div').each(function(el){
            $(this).removeClass('coloractive');
          })
          $(this).addClass('coloractive');
          curColor = $(this).attr('curColor');

          var selection = canvas.getActiveObject();
          if(selection){
            if(selection.type === 'activeSelection') {
              selection.forEachObject(function(element) {
                element.set('fill', curColor);
              });
            }
            else{
              selection.set('fill', curColor);
            }
            canvas.requestRenderAll();
          }
        });
        
      }
      
      //retrieve get Parameter from url
      function findGetParameter(parameterName) {
        var result = null,
            tmp = [];
        location.search
            .substr(1)
            .split("&")
            .forEach(function (item) {
              tmp = item.split("=");
              if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
            });
        return result;
      }

      function validateEmail(email) {
        var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return re.test(String(email).toLowerCase());
      }
      

});
@font-face {
    font-family: "PresidentPlain";
    src: url("../fonts/president.eot"); 
    src: url("./fonts/president.eot?#iefix") format("embedded-opentype"),
      url("../fonts/president.otf") format("opentype"), 
      url("../fonts/president.svg") format("svg"), 
      url("../fonts/president.ttf") format("truetype"), 
      url("../fonts/president.woff") format("woff"), 
      url("../fonts/president.woff2") format("woff2"); 
    font-weight: normal;
    font-style: normal;
  }
body{
    font-family: "Arial";
}
p{
  margin: 0;
}
.fontArial {
  font-size: 30px;


}
.fontPresident {
  font-family: 'PresidentPlain';
  font-size: 30px;

}

.canvasWrapper {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: center;
}

.legendWrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

.legendItems {
  width: 100%;
}

/* SLIDER/RADIOSELECT @ FONT */
.radiosliderwrapper {
  width: 100%;
  float: left;
}
.pdx-radio-slider {
  border: 2px solid #0077BA;
  display: inline-flex;
  position: relative;
  box-sizing: border-box;
  width: 100%;
}
.pdx-radio-slider .pdx-radio-slider__option {
  display: none;
}
.pdx-radio-slider label {
  z-index: 1;
  transition: color 0.4s ease;
  display: flex;
  color: #0077BA;
  width: 50%;
  height: 30px;
  margin: 7px;
  cursor: pointer;
  justify-content: center;
  align-items: center;
}
.pdx-radio-slider .pdx-radio-slider__option:checked + label {
  color: #fff;
}
.pdx-radio-slider .pdx-radio-slider__option:nth-child(1):checked ~ .pdx-radio-slider__slider {
  left: 0;
}
.pdx-radio-slider .pdx-radio-slider__option:nth-child(3):checked ~ .pdx-radio-slider__slider {
  left: 50%;
}
.pdx-radio-slider__slider {
  z-index: 0;
  width: 50%;
  height: 48px;
  position: absolute;
  top: -2px;
  background-color: #0077BA;
  transition: left 0.4s ease;
}
/* //SLIDER/RADIOSELECT @ FONT */


/*  COLORPALLET  */
.colorpallet {
  margin-top: 20px;
  width: 100%;
  float: left;
  background-color: #0077BA;
}

.colorwhite, .colorblack, .colorbrown {
  width: 21%;
  margin: 6%;
  float: left;
}
.colorwhite:before, .colorblack:before, .colorbrown:before {
  content: "";
  display: block;
  padding-top: 100%;  /* initial ratio of 1:1*/
}
.colorwhite{
  background-color: white;
}
.colorwhite:hover, .colorwhite.coloractive {
  background-color: #979A9A;
}

.colorbrown {
  background-color: #6E2C00;
}
.colorbrown:hover, .colorbrown.coloractive {
  background-color: #E67E22;
}
.colorblack {
  background-color: black;
}
.colorblack:hover, .colorblack.coloractive {
  background-color: #353535;
}
/*  //COLORPALLET  */

.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome and Opera */
}

.helpermsg{
  width: 100%;
  float: left;
  text-align: center;
  background-color: #0077BA; 
  border-top: 1px white solid;
  color: white;
  height: 40px;
  line-height: 40px;
  font-size: 15px;
}
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0 shrink-to-fit=no"/>
  <!DOCTYPE html>
<head>
	<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
  <script type="text/javascript" src="../scripts/fabric.min.js"></script>
    <script src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/javascript-canvas-to-blob/3.14.0/js/canvas-to-blob.min.js"></script>  
  <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

</head>
<body>


    <!-- 2D editor -->
        <div id="sendAlert" class="alert alert-success hidden" role="alert">
          Vielen Dank! Wir haben Ihr Bild erhalten. <a href="javascript:history.back();" class="alert-link">Hier kommen Sie wieder zur Galerie</a>.
        </div>


        <div id="canvasWrapper" class="canvasWrapper">
          <canvas id="canvas"></canvas>
        </div>
        <div class="legendWrapper">
          <div class="legendItems">
            <div class="radiosliderwrapper">
                <div class="pdx-radio-slider">
                  <input type="radio" class="pdx-radio-slider__option" id="first_toggle" name="font" value="Arial">
                  <label for="first_toggle" class="fontArial noselect">Arial</label>
                  <input type="radio" checked class="pdx-radio-slider__option" id="second_toggle" name="font" value="PresidentPlain">
                  <label for="second_toggle" class="fontPresident noselect">President</label>
                  <div class="pdx-radio-slider__slider">
                  </div>
                </div>
            </div>
              <div class="colorpallet">
                <div class="colorblack coloractive" curColor="#000000"></div>
                <div class="colorwhite" curColor="#FFFFFF"></div>
                <div class="colorbrown" curColor="#6E2C00"></div>
              </div>
              <span class="helpermsg noselect">Für neues Textfeld: DOPPELKLICK auf Bild</span>
              <div id="deleteSelected" class="btn btn-danger noselect mt-3" style=" width: 100%;">ausgewählte Textfelder löschen</div>
              <div class="btn btn-success noselect mb-5 mt-3" style="width: 100%;" data-toggle="modal" data-target="#exampleModal" id="modalBtn">speichern/abschicken</div>
          </div>
        </div>

</body>

</html>

0 个答案:

没有答案