3

I'm trying to build a t-shirt printing website and I'm currently stuck on how to correctly measure/calculate the position of the print on x/y axis and the print size itself.

You can get the idea of what I mean by

  1. visiting spreadshirt
  2. selecting any print
  3. trying to move / resize the print
  4. the measurement will be the same regardless of the screen/font size

I'm not sure how exactly the calculation happens but I was thinking that maybe I could get the device dpi then convert pixels to inches based on the result. But sadly that won't give correct measurements in many cases.

x00
  • 13,643
  • 3
  • 16
  • 40
ctf0
  • 6,991
  • 5
  • 37
  • 46

1 Answers1

0

You don't need dpi of anything of this sort.

Because you have a box (t-shirt in this case) of fixed and known size and position.

When a user moves an element inside the box you can calculate the element's position and size relative to the box.

And all you need to do is something like:

scale = box.width_in_inches / box.width_in_pixels
el.x_in_inches      = (el.x_in_pixels - box.x_in_pixels)*scale
el.y_in_inches      = (el.y_in_pixels - box.y_in_pixels)*scale
el.width_in_inches  = (el.width_in_pixels              )*scale
el.height_in_inches = (el.height_in_pixels             )*scale

box.width_in_inches can change when user selects t-shirt of a different size.
box.width_in_pixels will change when user zooms the page.
But all *_in_pixels values will change respectively.


Update: Answering to your comments:

  1. Maybe your're getting wrong measurements in your code because they are wrong from the beginning: the ratio of t-shirt's width and height

    1. in inches: 22 / 30.5 = 0.72...
    2. in pixels of the picture: 452 / 548 = 0,8248... (or on the page in my browser: 1428,750 / 1732,190 = 0,8248...)
    3. in pixels with bounds you've set up: (1428,750−160) / (1732,190−100) = 0,777...

      So I had to fix it somehow. I choose to remove the bounds, so that the logo can move and stretch inside the t-shirt picture freely. And decided that t-shirt width in inches should be 30.5*(452/548) = 25,157..., not 22.

  2. Then just as a sound check I set logo width to maximum and move it to the top. Now it's time for experiments. The expected results should be reasonably close to
    { x:0, y:0, w: 25,157, h: 9.07 }
  3. With this function:

    // const shirt_w_in_inches = 30.5*(452/548)
    const shirt_h_in_inches = 30.5
    
    function get_measurements() {
      const pixels_shirt = shirt.getBoundingClientRect()
      const pixels_logo  = logo .getBoundingClientRect()
      const scale = shirt_h_in_inches / pixels_shirt.height
      const inches = {
        x: (pixels_logo.x - pixels_shirt.x)*scale,
        y: (pixels_logo.y - pixels_shirt.y)*scale,
        w: (pixels_logo.width             )*scale,
        h: (pixels_logo.height            )*scale,
      }
    
      console.log("pixels_shirt", pixels_shirt)
      console.log("pixels_logo" , pixels_logo)
      console.log("inches"      , inches)
    
      return inches
    }
    

    I find them quite reasonable.

    The worst case I was able to find with an maximum error of around 1% of t-shirt width is when I set a 500% zoom, and refresh the page, and then if I resize my browser to 25% of initial window size (and I couldn't set it less). In this case I get these measurements:
    {x: 0.153..., y: 0.172..., w: 24.920..., h: 8.948...}

    But if I add inches.width and inches.x I will get 25.073 - which gives 0.3% - an average error I've observed.

  4. So you can ask: "What about x and y? They are never 0!".
    I'm sorry to break it to you but it looks like an issue with Moveable you're using. If I use this function:

    function set_full_size() {
      const pixels_shirt = shirt.getBoundingClientRect()
      const pixels_logo  = shirt.getBoundingClientRect()
      logo.style.left    = shirt.clientLeft  + 'px'
      logo.style.top     = shirt.clientTop   + 'px'
      logo.style.width   = shirt.clientWidth + 'px'
      logo.style.height  = shirt.clientHeight*pixels_logo.height/pixels_logo.clientWidth + 'px'
    }
    

    It not only sets zeros for x and y, but also you'll get a smaller error for width. Probably that's because of controls the Moveable puts around logo.

ctf0
  • 6,991
  • 5
  • 37
  • 46
x00
  • 13,643
  • 3
  • 16
  • 40
  • could u plz add an example ? – ctf0 May 26 '20 at 14:31
  • 1
    The site you've linked uses SVG, what do you use - I don't know. The data structures and field's names of yours - I don't know. How do you get the size of a t-shirt from a user - I also don't know. And I suppose you know how to get element's dimensions in pixels. So I don't really see what is missing from the code I've already provided. But If you'll update your question with a code example I'll be able to fix it. – x00 May 26 '20 at 17:00
  • sorry for the late reply, here is a [demo](https://jsfiddle.net/muah003/r9kfay7q/21) for the box measurements its `30.5inch H x 22inch W` – ctf0 May 30 '20 at 09:18
  • Sorry, right now I'm at That part of the world where I can't connect to jsfiddle :). And my VPN just broke. Can you put the code on github? – x00 May 31 '20 at 07:27
  • yeah sure, np [gist](https://gist.github.com/ctf0/943ae5d1008bfd75abe8e30245a9ce99) – ctf0 May 31 '20 at 08:38