即使水平滚动,如何使放置在 fabricjs 对象顶部的 DOM 元素保持在那里
How to make DOM element that is placed on top of fabricjs object stay there even when scrolling horizontally
我有一个 canvas,它有一个对象数组,这些对象被定位并添加到 canvas。
每个对象都有一个触发工具提示的匹配 DOM 元素。此元素正好位于 canvas 对象的顶部。
在桌面上这很好用,因为背景图像总是填满屏幕并且没有滚动条。但是在手机上我有一个水平滚动条,所以用户可以在图像上左右滚动(否则它会变得很小)。
问题是,位于织物对象顶部的 DOM 元素根据对象所在的位置停留在它们的位置而没有任何滚动,当我水平滚动时,DOM元素保持在同一个位置。
我在我的 phone 上制作了一个视频,展示了这一点: https://streamable.com/xn1t2i 带圆圈的点是 canvas 之外的 DOM 元素,这些元素位于 canvas 个对象(没有圆圈的蓝点)。
所以我想到了以下解决方案:将整个脚本放在一个函数中,然后在发生事件时调用该函数,例如:touchmove
然而,这非常慢,并且在四处移动时会出现很多闪烁.所以我尝试了 touchend
但这也很慢,并且在单击工具提示时也会触发该功能。
touchmove
的示例视频:https://streamable.com/708d2s 如您所见,点确实重新定位了,但是速度太慢了,如果滚动拖得太长,点就会错位再次.
我也试过 scroll
但这根本行不通。
这是我目前的代码:
javascript:
(function() {
function reRender(){
var myImg = document.querySelector("#background");
if(window.outerWidth > 767) {
menuheightcanvas = 172.5;
var realWidth = window.innerWidth;
var realHeight = myImg.naturalHeight;
}else{
menuheightcanvas = 99.8;
var realWidth = myImg.naturalWidth - 900;
var realHeight = myImg.naturalHeight;
}
var source = document.getElementById('background').src;
var canvas = new fabric.Canvas('c', {
allowTouchScrolling: true,
selection: false
});
canvas.allowTouchScrolling = true;
canvas.hoverCursor = 'pointer';
canvas.setDimensions({
width: realWidth,
height: realHeight
});
var img = new Image();
// use a load callback to add image to canvas.
img.src = 'https://printzelf.nl/new/assets/images/custom/WOONKAMER.jpg';
fabric.Object.NUM_FRACTION_DIGITS = 10;
fabric.Image.fromURL(source, function(img) {
img.scaleToWidth(canvas.width);
canvas.setBackgroundImage(img);
canvas.requestRenderAll();
});
var scaleToWidth = realWidth / myImg.width;
// alert (scaleToWidth)
const hotspots = [{
top: (140* scaleToWidth),
left: (720* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel1',
hoverCursor: 'pointer',
selectable: false,
imgtop: 71,
imgleft: 236,
imgheight: 335,
imgwidth: 514,
placement: 'right',
tooltipid: 'cirkel1',
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/gordijnen.jpg'
},
{
top: (160* scaleToWidth),
left: (640* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 82,
imgleft: 351,
imgheight: 313,
imgwidth: 337,
placement: 'right',
tooltipid: 'cirkel2',
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/voile.jpg'
},
{
top: (350* scaleToWidth),
left: (120* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel3',
hoverCursor: 'pointer',
selectable: false,
imgtop: 293,
imgleft: 21,
placement: 'right',
imgheight: 81,
imgwidth: 107,
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/fotoblok.jpg'
},
{
top: (275* scaleToWidth),
left: (165* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel4',
hoverCursor: 'pointer',
selectable: false,
imgtop: 283,
imgleft: 127,
placement: 'right',
imgheight: 60,
imgwidth: 57,
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/fotopaneel.jpg'
},
{
top: (430* scaleToWidth),
left: (600* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel5',
hoverCursor: 'pointer',
selectable: false,
imgtop: 365,
imgleft: 227,
placement: 'right',
imgheight: 185,
imgwidth: 396,
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/zitzak.jpg'
}
];
const loadedImages = [];
for (let [idx, props] of hotspots.entries()) {
let c = new fabric.Circle(props);
c.class = 'hotspot';
c.name = 'hotspot-' + idx;
canvas.add(c);
}
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + menuheightcanvas
};
}
var btnWidth = 40,
btnHeight = 40;
function positionBtn(obj, index) {
var absCoords = canvas.getAbsoluteCoords(obj);
var element = document.getElementById('cirkel' + index);
element.style.left = (absCoords.left - btnWidth / 10) + 'px';
element.style.top = (absCoords.top - btnHeight / 10) + 'px';
}
canvas.getObjects().forEach(function(ho, index) {
positionBtn(ho, index + 1);
});
$(".canvastip").each(function(i) {
tippy(this, {
theme: 'blue',
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
// popperOptions: {
// strategy: 'fixed',
// modifiers: [
// {
// name: 'flip',
// options: {
// fallbackPlacements: ['bottom', 'bottom'],
// },
// },
// {
// name: 'preventOverflow',
// options: {
// altAxis: true,
// tether: false,
// },
// },
// ],
// },
onShow(instance) {
canvas.getObjects().forEach(function(ho, index) {
if (ho.class && ho.class === 'hotspot') {
if (instance.id == index + 1) {
// check if image was previously loaded
if (loadedImages.indexOf(ho.name) < 0) {
// image is not in the array
// so it needs to be loaded
// prepare the image properties
let imgProps = {
width: ho.imgwidth,
height: ho.imgheight,
left: ho.imgleft* scaleToWidth,
top: ho.imgtop* scaleToWidth,
scaleX: 1* scaleToWidth,
scaleY: 1* scaleToWidth,
selectable: false,
id: 'img-' + ho.name,
hoverCursor: "default",
};
instance.setProps({placement: ho.placement})
var printzelfImg = new Image();
printzelfImg.onload = function(img) {
var printzelf = new fabric.Image(printzelfImg, imgProps);
printzelf.trippyHotspotImage = true;
canvas.add(printzelf);
};
printzelfImg.src = ho.imgUrl;
// update the `loadedImages` array
loadedImages.push(ho.name);
} else {
for (const o of canvas.getObjects()) {
if (o.id && o.id === 'img-' + ho.name) {
o.visible = true;
break;
}
}
canvas.renderAll();
}
}
}
});
},
onHide(instance) {
for (const o of canvas.getObjects()) {
if (o.trippyHotspotImage) {
o.visible = false;
}
}
canvas.renderAll();
},
content: function(reference) {
return reference.querySelector('.tooltipcontentcanvas' + (i + 1));
}
});
});
}
window.addEventListener('scroll', reRender, false);
reRender();
})();
HTML:
<img id="background" src="https://printzelf.nl/new/assets/images/custom/WOONKAMER.jpg" alt="" style="display:none;">
<div class="canvas-container" style="width: 100%; position: relative;">
<canvas id="c" width="100%" height="500" class="lower-canvas" style="position: absolute; width: 100%; height: 500px; left: 0px; top: 0px;"></canvas>
</div>
<span id="cirkel1" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas1 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/gordijnen" title="Weet je wat ik graag zou willen zijn?.." alt="Weet je wat ik graag zou willen zijn?.." class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/gordijnen.jpg" alt="Gordijnen">
</a>
<div class="tooltipinfo">
<span class="toptitle">Gordijnen</span>
<h2>Weet je wat ik graag zou willen zijn?..</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/gordijnen" title="Weet je wat ik graag zou willen zijn?.." alt="Weet je wat ik graag zou willen zijn?.."><span class="btnstyle purplebtn">Stel gordijnen samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel2" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas2 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/vitrage" title="Jouw vitrage wordt een rage!" alt="Jouw vitrage wordt een rage!" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/vitragegordijnen.jpg" alt="Vitragegordijnen">
</a>
<div class="tooltipinfo">
<span class="toptitle">Vitragegordijnen</span>
<h2>Jouw vitrage wordt een rage!</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/vitrage" title="Jouw vitrage wordt een rage!" alt="Jouw vitrage wordt een rage!"><span class="btnstyle purplebtn">Stel vitragegordijnen samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel3" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas3 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/fotoblok" title="Dit blok staat als een huis in je huis!" alt="Dit blok staat als een huis in je huis!" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/fotoblok.jpg" alt="Fotoblok">
</a>
<div class="tooltipinfo">
<span class="toptitle">Fotoblok</span>
<h2>Dit blok staat als een huis in je huis!</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/fotoblok" title="Dit blok staat als een huis in je huis!" alt="Dit blok staat als een huis in je huis!"><span class="btnstyle purplebtn">Stel fotoblok samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel4" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas4 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/foto-op-paneel" title="Zet jouw lievelingsfoto op een paneel" alt="Zet jouw lievelingsfoto op een paneel" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/fotopaneel.jpg" alt="Fotopaneel">
</a>
<div class="tooltipinfo">
<span class="toptitle">Fotopaneel</span>
<h2>Zet je lievelingsfoto op een paneel</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/foto-op-paneel" title="Zet jouw lievelingsfoto op een paneel" alt="Zet jouw lievelingsfoto op een paneel"><span class="btnstyle purplebtn">Stel fotopaneel samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel5" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas5 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/zitzak" title="Geniet rustig van jouw ontwerp" alt="Geniet rustig van jouw ontwerp" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/zitzak.jpg" alt="Zitzak">
</a>
<div class="tooltipinfo">
<span class="toptitle">Zitzakken</span>
<h2>Geniet rustig van jouw ontwerp</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/zitzak" title="Geniet rustig van jouw ontwerp" alt="Geniet rustig van jouw ontwerp"><span class="btnstyle purplebtn">Stel zitzak samen</span></a>
</div>
</div>
</div>
</span>
整个页面的代码笔:https://codepen.io/twan2020/pen/VwPZmJx 可能会尝试在您的 phone 上查看此内容,因为出于某种原因,当在桌面上将屏幕调整为移动尺寸时会破坏 canvas。不过在我的手机上它工作正常。
如何确保 DOM 元素点始终位于 canvas 对象点上?在保持当前速度的同时?
在你的 .canvas-container
和你的 #cirkel1 ... #cirkelN
div 周围包装一个新的相对位置 div
以便相关的 html 代码区域的结构如下:
<div class="canvas-container-container">
<div class="canvas-container">...</div>
<span id="cirkel1">...</span>
<span id="cirkel2">...</span>
...
</div>
重要的是 .canvas-container-container
有 position: relative;
以便相对于 .canvas-container-container
的原点定位其绝对定位子 #cirkel1 ... #cirkelN
。此更改意味着 .canvas-container-container
的起源对应于您 canvas 中的 (0,0)
点,这解决了您问题的根本问题。
更新您的 css 代码,使 .canvas-container
的 css 规则成为 canvas-container-container
的规则(确保删除相应的 .canvas-container
css代码):
.canvas-container-container {
position: relative;
height: 500px;
}
@media only screen and (max-width:991px) {
.canvas-container-container{
overflow-x:auto;
overflow-y:hidden;
}
.canvas-container-container,
.canvas-container {
height: 400px;
}
}
水平滚动应该已经可以工作了。但是,由于您的 #cirkel1 ... #cirkelN
现在相对于 .canvas-container-container
定位,因此您不再需要在 getAbsoluteCoords
中添加 this._offset.left
和 menuheightcanvas
:
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left, // +this._offset.left not needed here
top: object.top, // +menuheightcanvas not needed here
};
}
事实上,你甚至根本不需要这个 getAbsoluteCoords
,因为 obj.left 和 obj.top 已经相对于 canvas 原点,因此不需要偏移量:
function positionBtn(obj, index) {
var element = document.getElementById('cirkel' + index);
element.style.left = (obj.left - btnWidth / 10) + 'px';
element.style.top = (obj.top - btnHeight / 10) + 'px';
}
我有一个 canvas,它有一个对象数组,这些对象被定位并添加到 canvas。 每个对象都有一个触发工具提示的匹配 DOM 元素。此元素正好位于 canvas 对象的顶部。
在桌面上这很好用,因为背景图像总是填满屏幕并且没有滚动条。但是在手机上我有一个水平滚动条,所以用户可以在图像上左右滚动(否则它会变得很小)。
问题是,位于织物对象顶部的 DOM 元素根据对象所在的位置停留在它们的位置而没有任何滚动,当我水平滚动时,DOM元素保持在同一个位置。
我在我的 phone 上制作了一个视频,展示了这一点: https://streamable.com/xn1t2i 带圆圈的点是 canvas 之外的 DOM 元素,这些元素位于 canvas 个对象(没有圆圈的蓝点)。
所以我想到了以下解决方案:将整个脚本放在一个函数中,然后在发生事件时调用该函数,例如:touchmove
然而,这非常慢,并且在四处移动时会出现很多闪烁.所以我尝试了 touchend
但这也很慢,并且在单击工具提示时也会触发该功能。
touchmove
的示例视频:https://streamable.com/708d2s 如您所见,点确实重新定位了,但是速度太慢了,如果滚动拖得太长,点就会错位再次.
我也试过 scroll
但这根本行不通。
这是我目前的代码:
javascript:
(function() {
function reRender(){
var myImg = document.querySelector("#background");
if(window.outerWidth > 767) {
menuheightcanvas = 172.5;
var realWidth = window.innerWidth;
var realHeight = myImg.naturalHeight;
}else{
menuheightcanvas = 99.8;
var realWidth = myImg.naturalWidth - 900;
var realHeight = myImg.naturalHeight;
}
var source = document.getElementById('background').src;
var canvas = new fabric.Canvas('c', {
allowTouchScrolling: true,
selection: false
});
canvas.allowTouchScrolling = true;
canvas.hoverCursor = 'pointer';
canvas.setDimensions({
width: realWidth,
height: realHeight
});
var img = new Image();
// use a load callback to add image to canvas.
img.src = 'https://printzelf.nl/new/assets/images/custom/WOONKAMER.jpg';
fabric.Object.NUM_FRACTION_DIGITS = 10;
fabric.Image.fromURL(source, function(img) {
img.scaleToWidth(canvas.width);
canvas.setBackgroundImage(img);
canvas.requestRenderAll();
});
var scaleToWidth = realWidth / myImg.width;
// alert (scaleToWidth)
const hotspots = [{
top: (140* scaleToWidth),
left: (720* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel1',
hoverCursor: 'pointer',
selectable: false,
imgtop: 71,
imgleft: 236,
imgheight: 335,
imgwidth: 514,
placement: 'right',
tooltipid: 'cirkel1',
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/gordijnen.jpg'
},
{
top: (160* scaleToWidth),
left: (640* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 82,
imgleft: 351,
imgheight: 313,
imgwidth: 337,
placement: 'right',
tooltipid: 'cirkel2',
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/voile.jpg'
},
{
top: (350* scaleToWidth),
left: (120* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel3',
hoverCursor: 'pointer',
selectable: false,
imgtop: 293,
imgleft: 21,
placement: 'right',
imgheight: 81,
imgwidth: 107,
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/fotoblok.jpg'
},
{
top: (275* scaleToWidth),
left: (165* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel4',
hoverCursor: 'pointer',
selectable: false,
imgtop: 283,
imgleft: 127,
placement: 'right',
imgheight: 60,
imgwidth: 57,
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/fotopaneel.jpg'
},
{
top: (430* scaleToWidth),
left: (600* scaleToWidth),
radius: 10,
fill: '#009fe3',
id: 'cirkel5',
hoverCursor: 'pointer',
selectable: false,
imgtop: 365,
imgleft: 227,
placement: 'right',
imgheight: 185,
imgwidth: 396,
imgUrl: 'https://printzelf.nl/new/cms/images/canvas/woonkamer/zitzak.jpg'
}
];
const loadedImages = [];
for (let [idx, props] of hotspots.entries()) {
let c = new fabric.Circle(props);
c.class = 'hotspot';
c.name = 'hotspot-' + idx;
canvas.add(c);
}
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + menuheightcanvas
};
}
var btnWidth = 40,
btnHeight = 40;
function positionBtn(obj, index) {
var absCoords = canvas.getAbsoluteCoords(obj);
var element = document.getElementById('cirkel' + index);
element.style.left = (absCoords.left - btnWidth / 10) + 'px';
element.style.top = (absCoords.top - btnHeight / 10) + 'px';
}
canvas.getObjects().forEach(function(ho, index) {
positionBtn(ho, index + 1);
});
$(".canvastip").each(function(i) {
tippy(this, {
theme: 'blue',
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
// popperOptions: {
// strategy: 'fixed',
// modifiers: [
// {
// name: 'flip',
// options: {
// fallbackPlacements: ['bottom', 'bottom'],
// },
// },
// {
// name: 'preventOverflow',
// options: {
// altAxis: true,
// tether: false,
// },
// },
// ],
// },
onShow(instance) {
canvas.getObjects().forEach(function(ho, index) {
if (ho.class && ho.class === 'hotspot') {
if (instance.id == index + 1) {
// check if image was previously loaded
if (loadedImages.indexOf(ho.name) < 0) {
// image is not in the array
// so it needs to be loaded
// prepare the image properties
let imgProps = {
width: ho.imgwidth,
height: ho.imgheight,
left: ho.imgleft* scaleToWidth,
top: ho.imgtop* scaleToWidth,
scaleX: 1* scaleToWidth,
scaleY: 1* scaleToWidth,
selectable: false,
id: 'img-' + ho.name,
hoverCursor: "default",
};
instance.setProps({placement: ho.placement})
var printzelfImg = new Image();
printzelfImg.onload = function(img) {
var printzelf = new fabric.Image(printzelfImg, imgProps);
printzelf.trippyHotspotImage = true;
canvas.add(printzelf);
};
printzelfImg.src = ho.imgUrl;
// update the `loadedImages` array
loadedImages.push(ho.name);
} else {
for (const o of canvas.getObjects()) {
if (o.id && o.id === 'img-' + ho.name) {
o.visible = true;
break;
}
}
canvas.renderAll();
}
}
}
});
},
onHide(instance) {
for (const o of canvas.getObjects()) {
if (o.trippyHotspotImage) {
o.visible = false;
}
}
canvas.renderAll();
},
content: function(reference) {
return reference.querySelector('.tooltipcontentcanvas' + (i + 1));
}
});
});
}
window.addEventListener('scroll', reRender, false);
reRender();
})();
HTML:
<img id="background" src="https://printzelf.nl/new/assets/images/custom/WOONKAMER.jpg" alt="" style="display:none;">
<div class="canvas-container" style="width: 100%; position: relative;">
<canvas id="c" width="100%" height="500" class="lower-canvas" style="position: absolute; width: 100%; height: 500px; left: 0px; top: 0px;"></canvas>
</div>
<span id="cirkel1" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas1 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/gordijnen" title="Weet je wat ik graag zou willen zijn?.." alt="Weet je wat ik graag zou willen zijn?.." class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/gordijnen.jpg" alt="Gordijnen">
</a>
<div class="tooltipinfo">
<span class="toptitle">Gordijnen</span>
<h2>Weet je wat ik graag zou willen zijn?..</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/gordijnen" title="Weet je wat ik graag zou willen zijn?.." alt="Weet je wat ik graag zou willen zijn?.."><span class="btnstyle purplebtn">Stel gordijnen samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel2" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas2 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/vitrage" title="Jouw vitrage wordt een rage!" alt="Jouw vitrage wordt een rage!" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/vitragegordijnen.jpg" alt="Vitragegordijnen">
</a>
<div class="tooltipinfo">
<span class="toptitle">Vitragegordijnen</span>
<h2>Jouw vitrage wordt een rage!</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/vitrage" title="Jouw vitrage wordt een rage!" alt="Jouw vitrage wordt een rage!"><span class="btnstyle purplebtn">Stel vitragegordijnen samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel3" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas3 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/fotoblok" title="Dit blok staat als een huis in je huis!" alt="Dit blok staat als een huis in je huis!" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/fotoblok.jpg" alt="Fotoblok">
</a>
<div class="tooltipinfo">
<span class="toptitle">Fotoblok</span>
<h2>Dit blok staat als een huis in je huis!</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/fotoblok" title="Dit blok staat als een huis in je huis!" alt="Dit blok staat als een huis in je huis!"><span class="btnstyle purplebtn">Stel fotoblok samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel4" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas4 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/foto-op-paneel" title="Zet jouw lievelingsfoto op een paneel" alt="Zet jouw lievelingsfoto op een paneel" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/fotopaneel.jpg" alt="Fotopaneel">
</a>
<div class="tooltipinfo">
<span class="toptitle">Fotopaneel</span>
<h2>Zet je lievelingsfoto op een paneel</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/foto-op-paneel" title="Zet jouw lievelingsfoto op een paneel" alt="Zet jouw lievelingsfoto op een paneel"><span class="btnstyle purplebtn">Stel fotopaneel samen</span></a>
</div>
</div>
</div>
</span>
<span id="cirkel5" class="canvastip" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontentcanvas5 tooltipcontentcanvas darktext" style="position:relative;">
<div class="tooltipwrap">
<a href="product/zitzak" title="Geniet rustig van jouw ontwerp" alt="Geniet rustig van jouw ontwerp" class="tooltipprodlink">
<span class="tooltipprodlink">v.a. <b>€19,36</b> p/m<sup>2</sup></span>
<img class="tooltipimgprod" src="cms/images/canvas/woonkamer/tooltip/zitzak.jpg" alt="Zitzak">
</a>
<div class="tooltipinfo">
<span class="toptitle">Zitzakken</span>
<h2>Geniet rustig van jouw ontwerp</h2>
<span class="sub">
<ul>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">10 materialen</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">+ handige accessoires</li>
<li><img class="vinkje" src="https://printzelf.nl/new/assets/images/custom/vinkje.gif">Contourfrezen mogelijk</li>
</ul>
</span>
<a href="product/zitzak" title="Geniet rustig van jouw ontwerp" alt="Geniet rustig van jouw ontwerp"><span class="btnstyle purplebtn">Stel zitzak samen</span></a>
</div>
</div>
</div>
</span>
整个页面的代码笔:https://codepen.io/twan2020/pen/VwPZmJx 可能会尝试在您的 phone 上查看此内容,因为出于某种原因,当在桌面上将屏幕调整为移动尺寸时会破坏 canvas。不过在我的手机上它工作正常。
如何确保 DOM 元素点始终位于 canvas 对象点上?在保持当前速度的同时?
在你的 .canvas-container
和你的 #cirkel1 ... #cirkelN
div 周围包装一个新的相对位置 div
以便相关的 html 代码区域的结构如下:
<div class="canvas-container-container">
<div class="canvas-container">...</div>
<span id="cirkel1">...</span>
<span id="cirkel2">...</span>
...
</div>
重要的是 .canvas-container-container
有 position: relative;
以便相对于 .canvas-container-container
的原点定位其绝对定位子 #cirkel1 ... #cirkelN
。此更改意味着 .canvas-container-container
的起源对应于您 canvas 中的 (0,0)
点,这解决了您问题的根本问题。
更新您的 css 代码,使 .canvas-container
的 css 规则成为 canvas-container-container
的规则(确保删除相应的 .canvas-container
css代码):
.canvas-container-container {
position: relative;
height: 500px;
}
@media only screen and (max-width:991px) {
.canvas-container-container{
overflow-x:auto;
overflow-y:hidden;
}
.canvas-container-container,
.canvas-container {
height: 400px;
}
}
水平滚动应该已经可以工作了。但是,由于您的 #cirkel1 ... #cirkelN
现在相对于 .canvas-container-container
定位,因此您不再需要在 getAbsoluteCoords
中添加 this._offset.left
和 menuheightcanvas
:
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left, // +this._offset.left not needed here
top: object.top, // +menuheightcanvas not needed here
};
}
事实上,你甚至根本不需要这个 getAbsoluteCoords
,因为 obj.left 和 obj.top 已经相对于 canvas 原点,因此不需要偏移量:
function positionBtn(obj, index) {
var element = document.getElementById('cirkel' + index);
element.style.left = (obj.left - btnWidth / 10) + 'px';
element.style.top = (obj.top - btnHeight / 10) + 'px';
}