Heim  >  Artikel  >  Web-Frontend  >  Beispielcode-Freigabe für das Zuschneiden von JavaScript-Bildern ohne Verformung (Bild)

Beispielcode-Freigabe für das Zuschneiden von JavaScript-Bildern ohne Verformung (Bild)

黄舟
黄舟Original
2017-03-13 16:51:141761Durchsuche

Ich habe in letzter Zeit viele Methoden zum Zuschneiden von Bildern auf Websites durchsucht (Ausleihen eines Bildes von Script Home), indem die Größe des Zuschneidefelds geändert wird.

Aber dieser Artikel stellt eine andere Zuschneidemethode vor. Der Zuschneiderahmen wird vom Entwickler bestimmt und die Bildgröße wird vom Benutzer bestimmt . Wählen Sie die entsprechende Position durch Zoomen und Ziehen des Bildes aus und behalten Sie dabei immer das Seitenverhältnis des Bildes bei, wie im Bild oben rechts gezeigt.

Diese Methode hat hauptsächlich die folgenden Vorteile:

  1. Die Breite und Höhe des Zuschneiderahmens sollte mit dem tatsächlich verwendeten Seitenverhältnis übereinstimmen, um eine Bildverformung zu verhindern Probleme.

  2. Begrenzt die Anzeigegröße des Bildes nicht und stellt die Originalgröße des Bildes durch Skalierung sicher

  3. Zum teilweisen Zuschneiden ist es benutzerfreundlicher. Um beispielsweise einen sehr kleinen Teil eines hochauflösenden Bildes aufzunehmen, müssen wir das Bild nur vergrößern und in das Zuschneidefeld ziehen Das Zuschneidefeld muss auf eine sehr kleine Größe eingestellt werden, was der Benutzerbedienung nicht förderlich ist. Allerdings sollte ich auch über die Mängel sprechen um eine Größenordnung erhöht. . . .

  4. Die Hauptidee besteht darin, zwei Bilder zu verwenden, sie
absolut

zu positionieren, eines innerhalb des Zuschneiderahmens und das andere außerhalb des Zuschneiderahmens zu platzieren und den Transparenzeffekt, den Zuschneiderahmen, festzulegen

Überlauf

ist ausgeblendet, sodass die beiden Bilder jederzeit absolut synchron bleiben.

<p class="jimu-crop-image" data-dojo-attach-point="cropSection">
    <p class="viewer-box" data-dojo-attach-point="viewerBox">
        <p class="viewer-content" data-dojo-attach-point="viewerContent">
            <img class="viewer-image hide-image" data-dojo-attach-point="viewerImage" src="">
        </p>
        <img class="base-image hide-image" data-dojo-attach-point="baseImage" data-dojo-attach-event="mousedown:_onViewerMouseDown,mouseup:_onViewerMouseUp">

        <p class="controller">
            <p class="zoom-out" data-dojo-attach-event="click:_onZoomOutClick">-</p>
            <p class="slider" data-dojo-attach-point="sliderNode">
                <p class="button" data-dojo-attach-point="sliderButton" data-dojo-attach-event="mousedown:_onSliderMouseDown,mouseup:_onSliderMouseUp"></p>
                <p class="horizontal"></p>
            </p>
            <p class="zoom-in" data-dojo-attach-event="click:_onZoomInClick">+</p>
        </p>
    </p>
</p>
Binden Sie zunächst die Ereignisse „Mousemove“ und „Mousedown“

von Dokument

in postCreate wird weiterhin angezeigt. Sie können mit dem Ziehen oder Zoomen fortfahren. Die nächste Hauptarbeit liegt in den Startup- und _init

-Funktionen. Freunde, die mit Dojo nicht vertraut sind, müssen nur wissen, dass postCreate vor dem Start ausgeführt wird. Die folgenden Dinge werden hier erledigt:

startup: function() {
                var timeOut = /data:image\/(.*);base64/.test(this.imageSrc) ? 50 : 500;
                var tic = lang.hitch(this, function() {
                    var imageStyle = html.getComputedStyle(this.baseImage);
                    var imageWidth = parseFloat(imageStyle.width);
                    console.log(&#39;image width&#39;, imageWidth);
                    if (isFinite(imageWidth) && imageWidth > 0) {
                        this._init();
                    } else {
                        setTimeout(tic, timeOut);
                    }
                });

                setTimeout(tic, timeOut);
            },

_init: function() {
                debugger;
                var cropSectionStyle = html.getComputedStyle(this.cropSection);
                var cropSectionContentBox = html.getContentBox(this.cropSection);
                var imageStyle = html.getComputedStyle(this.baseImage);
                var imageWidth = parseFloat(imageStyle.width);
                var imageHeight = parseFloat(imageStyle.height);
                var imageRadio = imageWidth / imageHeight;

                this._maxImageWidth = imageWidth;
                this._maxImageHeight = imageHeight;

                if (imageHeight < this.realHeight && imageWidth < this.realWidth) {
                    alert(&#39;image is too smaller to display&#39;);
                    return;
                }

                //create a box which keep the ratio of width and height to full fill the content of popup
                this.idealWidth = this.realWidth;
                this.idealHeight = this.realHeight;

                this.ratio = this.ratio ? this.ratio : this.realWidth / this.realHeight;
                if (this.ratio >= 1) {
                    if (this.realWidth <= cropSectionContentBox.w) {
                        this.idealWidth += (cropSectionContentBox.w - this.realWidth) / 2;
                    } else {
                        this.idealWidth = cropSectionContentBox.w;
                    }
                    this.idealHeight = this.idealWidth / this.ratio;
                } else {
                    if (this.realHeight <= cropSectionContentBox.h) {
                        this.idealHeight += (cropSectionContentBox.h - this.idealHeight) / 2;
                    } else {
                        this.idealHeight = cropSectionContentBox.h;
                    }
                    this.idealWidth = this.idealHeight * this.ratio;
                }

                html.setStyle(this.viewerBox, {
                    width: this.idealWidth + &#39;px&#39;,
                    height: this.idealHeight + &#39;px&#39;
                });

                var paddingTop = Math.abs((parseFloat(cropSectionStyle.height) - this.idealHeight) / 2);
                html.setStyle(this.cropSection, {
                    &#39;paddingTop&#39;: paddingTop + &#39;px&#39;,
                    &#39;paddingBottom&#39;: paddingTop + &#39;px&#39;
                });

                // keep original ratio of image
                if (imageRadio >= 1) {
                    if (this.idealHeight * imageRadio >= this.idealWidth) {
                        html.setStyle(this.viewerImage, &#39;height&#39;, this.idealHeight + &#39;px&#39;);
                        html.setStyle(this.baseImage, &#39;height&#39;, this.idealHeight + &#39;px&#39;);
                    } else {
                        var properlyHeight = this._findProperlyValue(0, this.idealWidth, this.idealWidth, function(p) {
                            return p * imageRadio;
                        });
                        html.setStyle(this.viewerImage, &#39;height&#39;, properlyHeight + &#39;px&#39;);
                        html.setStyle(this.baseImage, &#39;height&#39;, properlyHeight + &#39;px&#39;);
                    }
                } else {
                    if (this.idealWidth / imageRadio >= this.idealHeight) {
                        html.setStyle(this.viewerImage, &#39;width&#39;, this.idealWidth + &#39;px&#39;);
                        html.setStyle(this.baseImage, &#39;width&#39;, this.idealWidth + &#39;px&#39;);
                    } else {
                        var properlyWidth = this._findProperlyValue(0, this.idealHeight, this.idealHeight, function(p) {
                            return p / imageRadio;
                        });
                        html.setStyle(this.viewerImage, &#39;width&#39;, properlyWidth + &#39;px&#39;);
                        html.setStyle(this.baseImage, &#39;width&#39;, properlyWidth + &#39;px&#39;);
                    }
                }

                query(&#39;.hide-image&#39;, this.domNode).removeClass(&#39;hide-image&#39;);

                imageStyle = html.getComputedStyle(this.baseImage);
                imageWidth = parseFloat(imageStyle.width);
                imageHeight = parseFloat(imageStyle.height);
                this._minImageWidth = imageWidth;
                this._minImageHeight = imageHeight;

                this._currentImageWidth = imageWidth;
                this._currentImageHeight = imageHeight;

                this._currentTop = -(imageHeight - this.idealHeight) / 2;
                this._currentLeft = -(imageWidth - this.idealWidth) / 2;
                html.setStyle(this.baseImage, {
                    top: this._currentTop + &#39;px&#39;,
                    left: this._currentLeft + &#39;px&#39;
                });
                html.setStyle(this.viewerImage, {
                    top: this._currentTop + &#39;px&#39;,
                    left: this._currentLeft + &#39;px&#39;
                });
                //sometimes zoomratio < 1; it&#39;s should be not allowed to zoom
                this._zoomRatio = this._maxImageWidth / this._minImageWidth;

                if (!this._latestPercentage) {
                    this._latestPercentage = 0;
                }
            },
Warten Sie, bis das Bild geladen ist und erhalten Sie die Originalgröße des Bildes, die bei der Berechnung verwendet wird Skalierungsfaktor später

  1. Achten Sie dabei auf das Seitenverhältnis des Zuschneidebereichs und lassen Sie den Zuschneidebereich den Arbeitsbereich so weit wie möglich ausfüllen. Das Wichtigste bei der Zuschneidearbeit besteht darin, eine Verformung des Bildes zu verhindern. Solange das Seitenverhältnis konsistent ist, kann der zugeschnittene Bereich entsprechend vergrößert werden.

  2. Behalten Sie das ursprüngliche Seitenverhältnis des Bildes bei und halten Sie das Bild so nah wie möglich am Zuschneiderahmen.

  3. Legen Sie die Anfangsposition fest Das Bild nach Abschluss der Berechnung auf der Maschine

  4. ist relativ einfach. Sie müssen nur die relativen Positionsänderungen der Maus aufzeichnen während der Bewegung und das kontinuierliche Ändern der linken und oberen Ecke in der oberen linken Ecke des Bildes verhindert, dass Elemente in Dragstart- und Selectstart-Ereignissen ausgewählt werden und blau werden.

  5. Das Hauptprinzip der Skalierung besteht darin,
die relative Position des Mittelpunkts des Zuschneiderahmens vor und nach der Skalierung unverändert beizubehalten

.

_resetImagePosition: function(clientX, clientY) {
                var delX = clientX - this._currentX;
                var delY = clientY - this._currentY;

                if (this._currentTop + delY >= 0) {
                    html.setStyle(this.baseImage, &#39;top&#39;, 0);
                    html.setStyle(this.viewerImage, &#39;top&#39;, 0);
                    this._currentY = clientY;
                    this._currentTop = 0;
                } else if (this._currentTop + delY <= this._maxOffsetTop) {
                    html.setStyle(this.baseImage, &#39;top&#39;, this._maxOffsetTop + &#39;px&#39;);
                    html.setStyle(this.viewerImage, &#39;top&#39;, this._maxOffsetTop + &#39;px&#39;);
                    this._currentY = clientY;
                    this._currentTop = this._maxOffsetTop;
                } else {
                    html.setStyle(this.baseImage, &#39;top&#39;, this._currentTop + delY + &#39;px&#39;);
                    html.setStyle(this.viewerImage, &#39;top&#39;, this._currentTop + delY + &#39;px&#39;);
                    this._currentY = clientY;
                    this._currentTop += delY;
                }

                if (this._currentLeft + delX >= 0) {
                    html.setStyle(this.baseImage, &#39;left&#39;, 0);
                    html.setStyle(this.viewerImage, &#39;left&#39;, 0);
                    this._currentX = clientX;
                    this._currentLeft = 0;
                } else if (this._currentLeft + delX <= this._maxOffsetLeft) {
                    html.setStyle(this.baseImage, &#39;left&#39;, this._maxOffsetLeft + &#39;px&#39;);
                    html.setStyle(this.viewerImage, &#39;left&#39;, this._maxOffsetLeft + &#39;px&#39;);
                    this._currentX = clientX;
                    this._currentLeft = this._maxOffsetLeft;
                } else {
                    html.setStyle(this.baseImage, &#39;left&#39;, this._currentLeft + delX + &#39;px&#39;);
                    html.setStyle(this.viewerImage, &#39;left&#39;, this._currentLeft + delX + &#39;px&#39;);
                    this._currentX = clientX;
                    this._currentLeft += delX;
                }
            },

Um den Mittelpunkt des skalierten ursprünglichen Zuschneiderahmens wieder an seine ursprüngliche Position zu verschieben, müssen wir den Median von berechnen Zwei Werte: Bildgröße Änderungsbetrag, der Betrag der Bewegung der oberen linken Ecke des Bildes.

Wobei _zoomRatio = _maxImageWidth / _minImageWidth; _maxImageWidth die Originalgröße des Bildes ist und _minImageWidth die Mindestbreite ist, die das Bild in die Nähe des Zuschneiderahmens bringt.

leftPercentage ist der Verschiebungsprozentsatz der Schiebetaste relativ zur Schiebeleiste.

var delImageWidth = this._minImageWidth * (this._zoomRatio - 1) * leftPercentage / 100;
var delImageHeight = this._minImageHeight * (this._zoomRatio - 1) * leftPercentage / 100;

var imageStyle = html.getComputedStyle(this.baseImage);
                this._currentLeft = parseFloat(imageStyle.left);
                this._currentTop = parseFloat(imageStyle.top);
var delImageLeft = (Math.abs(this._currentLeft) + this.idealWidth / 2) *
                    ((this._minImageWidth + delImageWidth) / this._currentImageWidth - 1);
var delImageTop = (Math.abs(this._currentTop) + this.idealHeight / 2) *
                    ((this._minImageWidth + delImageWidth) / this._currentImageWidth - 1);
_currentLeft und _currentTop sind die absolute Position des Bildes relativ zum Zuschneiderahmen vor dieser Skalierung (Position: absolut).

_currentImageWidth und _currentImageHeight sind die Größe des Bildes vor dieser Skalierung.

Das Einzige, was noch zu tun ist, ist, den Leerraum im Zuschneidefeld zu verhindern. Angenommen, der Benutzer vergrößert das Bild und zieht das Bild an den Rand, damit es mit dem Rand des Zuschneidefelds übereinstimmt. Wenn das Bild verkleinert wird, wird das Zuschneidefeld leer angezeigt. Um diese Situation zu verhindern, müssen auch wir entsprechende Maßnahmen ergreifen.

Wenn der obere linke Rand des Bildes mit dem oberen linken Rand des Zuschneidefelds übereinstimmt, ist der linke und obere Rand des Bildes immer gleich Null, unabhängig davon, wie Sie herauszoomen, und nur die Größe des Das Bild wird sich ändern.

Wenn der untere rechte Rand des Bildes mit dem unteren rechten Rand des Zuschneiderahmens übereinstimmt, kann der entsprechende linke und obere Rand basierend auf der Größe des Bildes und der Größe des Zuschneiderahmens berechnet werden

Das Obige sind die Implementierungsideen des Kunden. Alle Codes, Browserunterstützung: Moderne Browser und ie9+, ie8 werden später auch unterstützt.

服务器端使用nodejs+express框架,主要代码如下:

/**********
body: {
  imageString: base64 code
  maxSize: w,h
  cropOptions: w,h,t,l
}
************/
exports.cropImage = function(req, res) {
  var base64Img = req.body.imageString;
  if(!/^data:image\/.*;base64,/.test(base64Img)){
    res.send({
      success: false,
      message: &#39;Bad base64 code format&#39;
    });
  }
  var fileFormat = base64Img.match(/^data:image\/(.*);base64,/)[1];
  var base64Data = base64Img.replace(/^data:image\/.*;base64,/, "");
  var maxSize = req.body.maxSize;
  maxSize = maxSize.split(&#39;,&#39;);
  var cropOptions = req.body.cropOptions;
  cropOptions = cropOptions.split(&#39;,&#39;);

  try{
    var buf = new Buffer(base64Data, &#39;base64&#39;);
    var jimp = new Jimp(buf, &#39;image/&#39; + fileFormat, function() {
      var maxW = parseInt(maxSize[0], 10);
      var maxH = parseInt(maxSize[1], 10);
      var cropW = parseInt(cropOptions[0], 10);
      var cropH = parseInt(cropOptions[1], 10);
      var cropT = parseInt(cropOptions[2], 10);
      var cropL = parseInt(cropOptions[3], 10);
      this.resize(maxW, maxH)
      .crop(cropT, cropL, cropW, cropH);
    });

    jimp.getBuffer(&#39;image/&#39; + fileFormat, function(b) {
      var base64String = "data:image/" + fileFormat + ";base64," + b.toString(&#39;base64&#39;);
      res.send({
        success: true,
        source: base64String
      });
    });
  }catch(err) {
    logger.error(err);
    res.send({
      success: false,
      message: &#39;unable to complete operations&#39;
    });
  }
};


Das obige ist der detaillierte Inhalt vonBeispielcode-Freigabe für das Zuschneiden von JavaScript-Bildern ohne Verformung (Bild). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn