Sexual Ecologies Survey Tool: Refactored
by jude_pinto
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.27/interact.min.js"></script>
<div id="container">
<div class="circle" id="circle1" style="left: 250px; top: 50px; width: 150px; height: 150px;">
<span class="label">Circle 1</span>
</div>
<div class="circle" id="circle2" style="left: 150px; top: 200px; width: 150px; height: 150px;">
<span class="label">Circle 2</span>
</div>
<div class="circle" id="circle3" style="left: 350px; top: 200px; width: 150px; height: 150px;">
<span class="label">Circle 3</span>
</div>
</div>
<div id="instructions">Drag and Resize Circles.</div>
<div id="overlapInfo">Drag and Resize Circles. Overlap Areas:</div>
<button id="resetBtn">Reset</button>
CSS
body {
margin: 0;
font-family: sans-serif;
}
#container {
position: relative;
width: 100%;
height: 100vh;
background: #f0f0f0;
overflow: hidden;
}
.circle {
position: absolute;
border-radius: 50%;
border: 2px solid #333;
background-color: rgba(100, 149, 237, 0.4);
touch-action: none;
user-select: none;
display: flex;
justify-content: center;
align-items: center;
}
.label {
pointer-events: none; /* so it doesn't interfere with drag */
}
#instructions {
position: fixed;
top: 10px;
left: 10px;
background: white;
border: 1px solid #333;
padding: 10px;
max-width: 250px;
z-index: 1000;
}
#overlapInfo {
position: fixed;
top: 60px;
left: 10px;
background: white;
border: 1px solid #333;
padding: 10px;
max-width: 250px;
z-index: 1000;
}
#resetBtn {
position: fixed;
bottom: 10px;
left: 10px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #333;
color: white;
border: none;
border-radius: 4px;
z-index: 1000;
}
JavaScript
//Sexual Ecologies Interactive Survey Tool- Refactored
//By: Jude Pinto
// This code is a refactored version of an interactive survey for Aki Gormezano's study @ van Anders Lab.
//This program has imported the library interact.js, created by Taye.
//https://interactjs.io/
const originalStates = {};
const circles = document.querySelectorAll('.circle');
const overlapInfo = document.getElementById('overlapInfo');
// Save original states
circles.forEach(circle => {
originalStates[circle.id] = {
left: circle.style.left,
top: circle.style.top,
width: circle.style.width,
height: circle.style.height
};
});
// Enable dragging and resizing
circles.forEach(circle => {
interact(circle)
.draggable({
listeners: {
move(event) {
const target = event.target;
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
updateOverlapInfo();
}
}
})
.resizable({
edges: { left: true, right: true, top: true, bottom: true },
listeners: {
move(event) {
const target = event.target;
let width = parseFloat(target.style.width) || target.offsetWidth;
let height = parseFloat(target.style.height) || target.offsetHeight;
width += event.deltaRect.width;
height += event.deltaRect.height;
target.style.width = `${width}px`;
target.style.height = `${height}px`;
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.deltaRect.left;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.deltaRect.top;
target.style.transform = `translate(${x}px, ${y}px)`;
...