HTML SELECTION BOX

by João Vitor Scheuermann

HTML

<div id="layersWrapper" class="layersWrapper">
  <span class="label">CLICK AND DRAG:</span>
  <div id="selector" class="selector"></div>
</div>

SCSS

* {
  box-sizing: border-box;
  font-family: 'Roboto-Thin';
  letter-spacing: 5px;
  margin: 0;
  padding: 0;
}

html, body {
  width: 100%;
  height: 100%;
}

.layersWrapper {
  position: relative;
  width: 100%;
  height: 100%;
  background: #ffffff;
  overflow: scroll;
  
  > .label {
    display: block;
    margin: 20px;
    color: #000000;
    user-select: none;
  }
}

.selector {
  position: absolute;
  background: rgba(0, 0, 0, .1);
  border: 1px solid rgba(0, 0, 0, 1);
}

JavaScript

class Position {
  constructor(x, y, cb) {
    this._x = 0
    this._y = 0
    this._callback = cb
  }

  get x() {
    return this._x
  }
  set x(value) {
    this._x = value
    this._callback(this)
  }

  get y() {
    return this._y
  }
  set y(value) {
    this._y = value
    this._callback(this)
  }

}

let app = {
  elements: {
    layersWrapper: document.getElementById('layersWrapper'),
    selector: document.getElementById('selector')
  },
  data: {
  	bounds: null,
    pressed: false,
    mouseStartPosition: new Position(0, 0, update),
    mouseCurrentPosition: new Position(0, 0, update),
    scroll: new Position(0, 0, update)
  }
}

function relativeToBoundsEvent (e) {
 	return {
  	x: e.x - app.data.bounds.x,
    y: e.y - app.data.bounds.y
  }   	
}

app.data.bounds = app.elements.layersWrapper.getBoundingClientRect()

app.elements.layersWrapper.addEventListener('mousedown', e => {
  app.data.pressed = true
  
  let event = relativeToBoundsEvent(e)

  app.data.mouseStartPosition.x = event.x + app.data.scroll.x
  app.data.mouseStartPosition.y = event.y + app.data.scroll.y

  app.data.mouseCurrentPosition.x = event.x + app.data.scroll.x
  app.data.mouseCurrentPosition.y = event.y + app.data.scroll.y

  console.log(JSON.stringify(app.data))
})

document.addEventListener('mouseup', e => {
  console.log(JSON.stringify(app.data))

  app.data.pressed = false
  app.data.mouseStartPosition.x = 0
  app.data.mouseStartPosition.y = 0

  app.data.mouseCurrentPosition.x = 0
  app.data.mouseCurrentPosition.y = 0
})

app.elements.layersWrapper.addEventListener('scroll', e => {
  app.data.scroll.x = e.target.scrollLeft
  app.data.scroll.y = e.target.scrollTop
})

app.elements.layersWrapper.addEventListener('mousemove', e => {  
  if (app.data.pressed) {
  	let event = relativeToBoundsEvent(e)
    app.data.mouseCurrentPosition.x = event.x + app.data.scroll.x
  	app.data.mouseCurrentPosition.y = event.y + app.data.scroll.y
  }
})

function update() {
  let startX =...