Give your hero section a dynamic and fresh look with this section tutorial. Select up to 5 images, alter the text size, and add a punchy background colour to craft a unique experience. Crafted with responsiveness in mind, the design looks impeccable across desktop and mobile platforms.
<div id="canvas-parent">
<div class="hover-text page-width">
<h1 class="image-hover-h1"> {{section.settings.heading-text}} </h1>
<a href="{{section.settings.button-link}}" class="button button-custom"> {{section.settings.button-text}} </a>
</div>
</div>
{% schema %}
{
"name": "Image Cursor Hero",
"tag": "section",
"settings": [
{
"type": "image_picker",
"id": "image1",
"label": "Image 1"
},
{
"type": "image_picker",
"id": "image2",
"label": "Image 2"
},
{
"type": "image_picker",
"id": "image3",
"label": "Image 3"
},
{
"type": "image_picker",
"id": "image4",
"label": "Image 4"
},
{
"type": "image_picker",
"id": "image5",
"label": "Image 5"
},
{
"type": "range",
"id": "image-size",
"min": 1,
"max": 8,
"step": 1,
"label": "Image Size",
"default": 5
},
{
"type": "text",
"id": "heading-text",
"label": "Heading Text"
},
{
"type": "range",
"id": "heading-size",
"min": 6,
"max": 12,
"step": 2,
"unit": "rem",
"label": "Heading size",
"default": 8
},
{
"type": "text",
"id": "button-text",
"label": "Button Text"
},
{
"type": "url",
"id": "button-link",
"label": "Button Link"
},
{
"type": "color",
"id": "text-color",
"label": "Text Color",
"default": "#121212"
},
{
"type": "color",
"id": "background-color",
"label": "Background Color",
"default": "#FFFFFF"
},
{
"type": "color",
"id": "button-text-color",
"label": "Button Text Color",
"default": "#121212"
}
],
"presets": [
{"name": "Image Cursor Hero" }
],
"limit": 1
}
{% endschema %}
<style>
#canvas-parent {
height: 80vh;
overflow: hidden;
background-color: {{section.settings.background-color}};
}
.p5Canvas {
position: relative!important;
}
.hover-text {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 80vh;
z-index: 2;
position: absolute;
flex-direction: column;
text-align: center;
max-width: none!important;
}
.image-hover-h1 {
font-size: {{ section.settings.heading-size}}rem;
color: {{ section.settings.text-color}};
line-height: 100%;
margin: 4rem;
max-width: 850px;
}
.button-custom {
color: {{section.settings.button-text-color}};
}
@media screen and (max-width:500px) {
.image-hover-h1 {
font-size:{{ section.settings.heading-size | divided_by: 1.5}}rem!important;
margin: 2.5rem;
}
.hover-text {
height: 50vh;
}
#canvas-parent {
height: 50vh
}
}
</style>
<script src="https://cdn.jsdelivr.net/npm/p5@1.6.0/lib/p5.js"></script>
<script>
let imageUrls = [
"{{ section.settings.image1 | image_url }}",
"{{ section.settings.image2 | image_url }}",
"{{ section.settings.image3 | image_url }}",
"{{ section.settings.image4 | image_url }}",
"{{ section.settings.image5 | image_url }}",
];
// distance mouse needs to move before next image is shown
let distThreshold = 45;
// scale factor to size images
let scaleFactor = {{section.settings.image-size}};
// VARIABLES
// array to hold all of our images
let images = [];
// array to hold history of mouse positions and image index for that position
let queue = [];
// object containing our last (stored) mouse position
let lastMousePos = { x: 0, y: 0 };
// current image to show
let imgIndex = 0;
// load all of the images from their urls into the images array
function preload() {
for (let i = 0; i < imageUrls.length; i++) {
images[i] = loadImage(imageUrls[i]);
}
}
// setup canvas and store initial mouse position
function setup() {
let cnv = createCanvas(windowWidth, windowHeight);
cnv.parent("canvas-parent");
cnv.style("display", "block");
cnv.style("position", "absolute");
cnv.style("inset", "0");
cnv.style("z-index", "1");
lastMousePos = { x: mouseX, y: mouseY };
}
function draw() {
// clear the canvas
clear();
// calculate distance between current mouse position and last stored mouse position.
let d = dist(mouseX, mouseY, lastMousePos.x, lastMousePos.y);
// If distance is greater than threshold:
// 1. Add current mouse position and current image index to the front of the queue
// 2. Update lastMousePos to current mouse position
// 3. Update imgIndex to next image index
if (d > distThreshold) {
queue.unshift({ x: mouseX, y: mouseY, index: imgIndex });
lastMousePos = { x: mouseX, y: mouseY };
imgIndex = (imgIndex + 1) % images.length;
}
// maintain queue length equal to number of images by removing the last item
if (queue.length > images.length) {
queue.pop();
}
// define scale of images based on width of canvas
let scale = width / scaleFactor;
// draw images in queue
// draw order is reversed so that the first image in the queue is drawn on top
for (let i = queue.length - 1; i >= 0; i--) {
let img = images[queue[i].index];
if (img) {
// scale image based on scale factor
let imgWidth = (img.width * scale) / img.width;
let imgHeight = (img.height * scale) / img.width;
// draw image at mouse position offset by half of image width and height
image(
img,
queue[i].x - imgWidth / 2,
queue[i].y - imgHeight / 2,
imgWidth,
imgHeight
);
}
}
}
// resize canvas when window is resized
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
</script>