JSFiddle - React, Tailwind, and code Playground

by rough cheap

HTML

<div class="header wrapper">
  <div class="header-content">ヘッダー</div>
</div>
<div class="body wrapper">
  <h3>コンテンツ</h3>
  <div class="container">
    <div class="control-panel">
      <button type="button" id="button1">Button1</button>
      <button type="button">Button2</button>
      <input type="checkbox" id="selectRange" />
      <label for="selectRange">Select range.</label>
    </div>
    <div id="canvasContainer" class="container canvas-container">
      <div id="textLayer" class="text-layer">Text Layer.</div>
      <div id="redRect" class="red-rect"></div>
    </div>
    <div id="statusLine" class="status">&nbsp;</div>
  </div>
  <h3>コンテンツ2</h3>
  <div style="height: 300px"></div>
</div>
<div class="footer wrapper">
  <div class="footer-content">フッター</div>
</div>

CSS

body {
  padding: 0px;
  margin: 0;
}
div, h3, p {
  box-sizing: border-box;
}
.wrapper {
  padding: 40px;
}

.header, .footer {
  background-color: grey;
  color: white;
}

.control-panel, .status {
  padding-top: 10px;
  padding-bottom: 10px;
}

.canvas-container {
  position: relative;
  width: 100%;
  height: 320px;
  overflow: auto;
}

.red-rect {
  position: absolute;
  top:0;
  left:0;
  display: none;
}

.is-drawing .red-rect {
  display: block;
}

.red-rect:after {
  content: ' ';
  position: absolute;
  top: var(--red-rect-top);
  left: var(--red-rect-left);
  width: var(--red-rect-width);
  height: var(--red-rect-height);
  border: 2px solid red;
}

.text-layer {
  width: 1280px;
  height: 720px;
  background-color: #c6c6c6;
}

JavaScript

const canvasContainer = document.getElementById("canvasContainer")
const textLayer = document.getElementById("textLayer")
const statusLine = document.getElementById("statusLine")
const redRect = document.getElementById("redRect")
const selectRange = document.getElementById("selectRange")
const button1 = document.getElementById("button1")
const startPos = { x: 0, y: 0 }
var isDrawing = false
var isSelectRange = false

redRect.addEventListener("mousemove", (e) => {
  e.stopPropagation()
  e.preventDefault()
  const mouseEvent = new MouseEvent('mousemove', e);
  textLayer.dispatchEvent(mouseEvent);
});

textLayer.addEventListener("mousemove", (e) => {
  e.stopPropagation()
  e.preventDefault()

  if (e.buttons & (1 === 1)) {
    console.log("mouse moving with keeping left button down")
    const endPos = {
    	x: e.offsetX,
      y: e.offsetY
    }
    drawrect(startPos, endPos);
  } else {
    console.log("mouse moving")
  }

  const targetRect = textLayer.getBoundingClientRect()
  const parentRect = canvasContainer.getBoundingClientRect()
  const parentW = parentRect.right - parentRect.left
  const parentH = parentRect.bottom - parentRect.top

  statusLine.innerText = `offsetX:${e.offsetX} offsetY:${e.offsetY}
  parent    boundX:${parentRect.left} boundY:${parentRect.top} parentW:${parentW} parentH:${parentH}
  textLayer boundX:${targetRect.left} boundY:${targetRect.top}
  hiddenTextLayerX:${parentRect.left - targetRect.left} Y:${parentRect.top - targetRect.top}
  visibleTextLayerX:${e.offsetX - (parentRect.left - targetRect.left)} Y:${e.offsetY - (parentRect.top - targetRect.top)}
  textLayer offsetTop:${textLayer.offsetLeft} offsetLeft:${textLayer.offsetTop}
  pageX:${e.pageX} pageY:${e.pageY}
  clientX:${e.clientX} clientY:${e.clientY}
  document.documentElement.scrollTop:${document.documentElement.scrollTop}`
  
})

function drawrect(p1, p2) {
	let aX = [p1.x, p2.x].sort((a1, a2) => a1 - a2)
  let aY = [p1.y, p2.y].sort((a1, a2) => a1 - a2)
  let w = aX[1] -...