1

I am working on a made-to-measure framing website and need to display an example of the frame on the screen while the customer is entering their dimensions. I have got most of it done, with the current issue being how to crop the corner of an image. I am using a HTML Canvas element.

The dimensions input and the frame display will be within a Vue JS component.

The image being used is a straight peice of the frame.

So far I have managed to get the frame to repeat all around the canvas, at the correct aspect ratio with repect to the dimensions. The way I have achived that is start with the top side, repeat the image across, then rotate the canvas 90 degrees, repeat the image down the right side, rotate 90 degrees again, repeat the image along the bottom, the rotate the canvas again and repeat the image down the left side.

Once the component is "mounted":

mounted() {
    let self = this

    window.addEventListener('load', function (e) {            
      self.canvas = document.getElementById('selected-frame')
      self.ctx = self.canvas.getContext('2d')

      self.setDims()            
    })
}
setDims: function() {
    let ratio = this.calculateAspectRatioFit(
        this.frameWidth,
        this.frameHeight,
        800,
        500
    )

    this.canvas.width = ratio.width
    this.canvas.height = ratio.height

    this.ctx.fillStyle = 'green'
    this.ctx.fillRect(0, 0, ratio.width, ratio.height)

    let pixelsPerMm = this.canvas.width / this.frameWidth

    let img = document.getElementById("moulding-6210PT")

    let mouldingImgRatio = this.calculateAspectRatioFit(
        img.width,
        img.height,
        800,
        this.mouldingWidth * pixelsPerMm
    )

    let runningLength = 0
    let i = 0

    // Top
    for (i; runningLength < this.canvas.width; i++) {
        runningLength = runningLength + mouldingImgRatio.width

        this.ctx.drawImage(img, mouldingImgRatio.width * i, 0, mouldingImgRatio.width, mouldingImgRatio.height)
    }

    // Right
    this.ctx.rotate((Math.PI/180) * 90) // Rotate 90 degrees
    runningLength = 0
    i = 0
    for (i; runningLength < this.canvas.height; i++) {
        runningLength = runningLength + mouldingImgRatio.width

        this.ctx.drawImage(img, mouldingImgRatio.width * i, -ratio.width, mouldingImgRatio.width, mouldingImgRatio.height)
    }

    // Bottom
    this.ctx.rotate((Math.PI/180) * 90) // Rotate another 90 degrees
    runningLength = 0
    i = 0
    for (i; runningLength < this.canvas.width; i++) {
        runningLength = runningLength + mouldingImgRatio.width

        this.ctx.drawImage(img, -ratio.width + (mouldingImgRatio.width * i), -ratio.height, mouldingImgRatio.width, mouldingImgRatio.height)
    }

    // Left
    this.ctx.rotate((Math.PI/180) * 90) // Rotate another 90 degrees
    runningLength = 0
    i = 0
    for (i; runningLength < this.canvas.height; i++) {
        runningLength = runningLength + mouldingImgRatio.width

        this.ctx.drawImage(img, -ratio.height + (mouldingImgRatio.width * i), 0, mouldingImgRatio.width, mouldingImgRatio.height)
    }
}

Method to calculate the aspect ratio (Taken from https://stackoverflow.com/a/14731922/1520367):

calculateAspectRatioFit: function(srcWidth, srcHeight, maxWidth, maxHeight) {
    var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
    return { width: srcWidth*ratio, height: srcHeight*ratio };
},

I need a way to re-shape the image of the peice of frame so the corners look like thay have been cut and joined at a right-angle. Any suggestions would really be appreciated.

Here is what I have achieved so far:

enter image description here

Here is what I want to achieve:

enter image description here

Here is the image of the peice of frame I am using: enter image description here

Jamal Ali
  • 109
  • 6

1 Answers1

0

It looks like you're going to have to use SVG clipPath: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath

This will allow you to specify the exact points to clip, fairly similar to have you're already laying out your images.

I originally posted that you could use PNGs with pre-cut corners, but then read your question again and realized you're repeating the images. If you can get the frame image at a high enough resolution you should be able to have it fill the whole width without having to repeat it. Then you could use PNGs and avoid using the SVG clipPath altogether.

Jamie T
  • 101
  • 7