JSFiddle - React, Tailwind, and code Playground
by Pangur Ban
HTML
<div class="chart">
<div class="chart_container">
<div class="chart_wrapper">
<div class="chart_canvas">
<span>canvas</span>
</div>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
</div>
</div>
</div>
SCSS
.chart {
overflow: auto;
position: relative;
// test
//width: 300px;
height: 300px;
border: 2px solid red;
/// ---
&_container {
padding: 20px;
display: inline-block;
}
&_wrapper {
position: relative;
}
&_canvas {
// test
position: relative;
background: rgba(0, 0, 0, 0.1);
font: 30px sans-serif;
text-align: center;
//---
span {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
}
[class^=box] {
position: absolute;
width: 100px;
height: 40px;
border: 2px solid #999;
}
.box1 {
top: 0;
left: 0;
}
.box2 {
top: 0;
right: 0;
}
.box3 {
bottom: 0;
left: 0;
}
.box4 {
bottom: 0;
right: 0;
}
.box5 {
transform: translate(-50%, -50%);
left: 50%;
top: 50%;
}
Babel + JSX
class CanvasPosition {
constructor(wrapperWidth, wrapperHeight) {
this.wrapperWidth = wrapperWidth;
this.wrapperHeight = wrapperHeight;
this.init();
this.layoutCanvas();
this.positionCanvas();
}
init() {
this.chartEl = document.querySelector('.chart');
this.containerEl = this.chartEl.querySelector('.chart_container');
this.wrapperEl = this.chartEl.querySelector('.chart_wrapper');
this.canvasEl = this.chartEl.querySelector('.chart_canvas');
this.chartEl.addEventListener('scroll', e => this.positionCanvas());
window.addEventListener('resize', e => {
this.layoutCanvas();
this.positionCanvas();
});
}
layoutCanvas() {
this.wrapperEl.style.width = `${this.wrapperWidth}px`;
this.wrapperEl.style.height = `${this.wrapperHeight}px`;
const chartWidth = this.chartEl.clientWidth;
const chartHeight = this.chartEl.clientHeight;
const canvasWidth = Math.min(this.wrapperWidth, chartWidth);
const canvasHeight = Math.min(this.wrapperHeight, chartHeight);
const containerWidth = this.containerEl.clientWidth;
this.margin = (containerWidth - this.wrapperWidth) / 2;
this.leftLimit = this.wrapperWidth - canvasWidth + this.margin;
this.topLimit = this.wrapperHeight - canvasHeight + this.margin;
let left = 0;
if (containerWidth < chartWidth) {
left = (chartWidth - containerWidth) / 2;
}
this.canvasEl.style.width = `${canvasWidth}px`;
this.canvasEl.style.height = `${canvasHeight}px`;
this.wrapperEl.style.left = `${left}px`;
}
positionCanvas() {
const scrollTop = this.chartEl.scrollTop;
const scrollLeft = this.chartEl.scrollLeft;
let top = (scrollTop > this.topLimit) ? this.topLimit : scrollTop;
if (top < this.margin) {
top = 0;
} else {
top -= this.margin;
}
let left = (scrollLeft > this.leftLimit) ? this.leftLimit : scrollLeft;
if (left < this.margin) {
left = 0;
} else {
...