Подобных вещей еще не приходилось реализовывать, по этому нуждаюсь в помощи выбора оптимального способа реализации.
Постараюсь максимально понятно объяснить, что нужно сделать.
Есть блок с изображением, при попадании курсора в область этого блока, курсор заменяется на прямоугольный блок (возможно прозрачное изображение с рамкой), под которым начинает просвечиваться блок с изображением, а под ним в свою очередь, находится другое изображение часть которого становится видна. Получается что-то вроде clip-path
как здесь http://www.cssplant.com/clip-path-generator только вместо белого фона другое изображение и желательно иметь возможно как-то стилизовать просвечиваемую область, возможно даже размещать в ней какие-то еще элементы. Также на заднем фоне, есть активные области и если они попадают в область просмотра под курсором, нужно это отлавливать.
Предполагаю, что нужно смотреть в сторону canvas'a. Если вдруг кто-то реализовывал подобное или имеет понятие как это можно осуществить, возможно знаете готовые библиотеки для подобных решений, буду рад любой помощи.
Что-то подобное соорудил на svg
+ js
Эффект достигается за счет clip-path
и подсчета расстояния от курсора до активных зон.
// точка, для пересчета координат мыши в координаты svg холста
var pt = svg.createSVGPoint();
// активные зоны
var zones = document.querySelectorAll('.zone');
addEventListener('mousemove', e => {
// так получаем координаты мыши относительно холста
pt.x = e.clientX;
pt.y = e.clientY;
let p = pt.matrixTransform(svg.getScreenCTM().inverse());
// позиционируем clip-path
clipRect.setAttribute('x', p.x - 7.5);
clipRect.setAttribute('y', p.y - 17);
// позиционируем телефон
phone.setAttribute('x', p.x - 12.5);
phone.setAttribute('y', p.y - 25);
text.setAttribute('x', p.x);
text.setAttribute('y', p.y + 13);
text.innerHTML = '';
// перебираем все зоны
zones.forEach(z => {
// текущая прозрачность активной зоны
let o = z.style.opacity;
// новое значение прозрачности на основании теста попадания круга в прямоугольник
z.style.opacity = test(z, clipRect) ? 1 : 0;
+z.style.opacity && (text.innerHTML = z.id);
// если значение прозрачности изменилось с 0 на 1 вызываем callback
+z.style.opacity - o === 1 && callback(z.id);
})
})
function test(zone, rect) {
var zx = +zone.getAttribute('cx');
var zy = +zone.getAttribute('cy');
var zr = +zone.getAttribute('r');
var rx = +rect.getAttribute('x');
var ry = +rect.getAttribute('y');
var rw = +rect.getAttribute('width');
var rh = +rect.getAttribute('height');
return zx - zr > rx && zx + zr < rx + rw &&
zy - zr > ry && zy + zr < ry + rh;
}
function callback(id) {
console.log(id)
}
<body style="margin:0;overflow:hidden;">
<svg viewBox="0 0 200 100" height="100vh" id="svg" style="cursor:none;">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="200" height="100">
<image xlink:href="https://picsum.photos/id/1/800/400" width="200" height="100"/>
</pattern>
<pattern id="img2" patternUnits="userSpaceOnUse" width="200" height="100">
<image xlink:href="https://picsum.photos/id/2/800/400" width="200" height="100"/>
</pattern>
<clipPath id="clip">
<rect id="clipRect" width="15" height="34"></rect>
</clipPath>
</defs>
<rect width="200" height="100" fill="url(#img1)"></rect>
<rect width="200" height="100" fill="url(#img2)" clip-path="url(#clip)"></rect>
<circle id="zone1" class="zone" cx="20" cy="20" r="2"></circle>
<circle id="zone2" class="zone" cx="50" cy="70" r="4"></circle>
<circle id="zone3" class="zone" cx="120" cy="30" r="5"></circle>
<circle id="zone4" class="zone" cx="150" cy="80" r="3"></circle>
<image id="phone" width="25" height="50"
xlink:href="https://www.searchpng.com/wp-content/uploads/2018/12/Apple-iPhone-XR-715x1090.png"></image>
<text id="text" text-anchor="middle" alignment-baseline="middle" font-size="5" fill="white"></text>
<style>
.zone {
fill:red;
opacity:0;
}
</style>
</svg>
</body>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Почему при копировании CSS кода из одного файла и его вставке в другой CSS файл разметка выглядит по-другому? Я разметил каркас, который нужен...
У меня есть 8 элементов расположеных в два ряда по горизонталиДля позиционирования, я использовал CSS Grid Layout