javascript - 悬停时更改画布内的图像
问题描述
我想在悬停状态下替换画布内的图像。棘手的部分是图像漂浮在它们的容器内。
问题
当移动项目悬停在画布内时如何运行函数。
我试过的
首先,我使用mouseenter
、mousemove
和onmousemove
函数来捕获悬停的项目。
当前问题
即使我可以在悬停状态下捕获项目,它也无法正常工作。有时,当您在画布上移动光标时,即使光标超出其边界,它仍会记录一个项目。
笔记
在当前版本中,没有不同的图像可以交换,我只是想先获取元素。唯一的变化(悬停状态)将是项目的背景颜色,所以我尝试使用内联 SVG(以轻松更改填充属性),但内联 SVG 元素没有显示在 Firefox 上并且在 Safari 上被扭曲。因此,我回到使用图像。
代码片段
悬停代码在init
函数内部。我没有简化代码以防万一您想查看整个结构,对不起质量!
( function( $ ){
'use strict';
const bouncer = {
// Canvas element
//
canvas: '',
// Context (of canvas)
//
ctx: '',
speed_m: 1, // Speed constant to multiply
speed_a: 2, // Speed constant to add
speed_r: 1.5, // Rotating speed
// Array of bouncing objects
//
items: [],
init: function() {
const self = window.kpBouncer;
self.canvas = $( '#canvas' )[0];
self.ctx = canvas.getContext('2d')
self.canvas.width = $( '#canvas' ).width();
self.canvas.height = $( '#canvas' ).height();
self.canvas.addEventListener( 'click', self.canvas_click, false );
self.canvas.onmousemove = function( ev ) {
const mouse_x = ev.layerX;
const mouse_y = ev.layerY;
const item_hovered = self.items.find(function( item ) {
const left = ( item.x - item.width );
const right = ( item.x + item.width );
const top = ( item.y - item.height );
const bottom = ( item.y + item.height );
if ( mouse_x < left ) {
return false; }
if ( mouse_x > right ) {
return false; }
if ( mouse_y < top ) {
return false; }
if ( mouse_y > bottom ) {
return false; }
return item;
});
if ( !item_hovered ) {
return; }
console.log( 'Hovered sticker is: ', item_hovered.id );
}
self.items = [];
$( '.rotating-icon:not([disabled])' ).each( function( idx, el ) {
const id = $( el ).prop( 'id' );
const link = $( el ).data( 'link' );
const w = $( el ).data( 'w' );
const h = $( el ).data( 'h' );
const x = self.random( w, ( self.canvas.width - w ) );
const y = self.random( h, ( self.canvas.height - h ) );
const item = {
id: id,
el: el,
width: w,
height: h,
rotate: 0,
link: ( link || '' ),
x: x,
y: y,
vel_x: (Math.random() * self.speed_m + self.speed_a) * (Math.floor(Math.random() * self.speed_m) || -1),
vel_y: (Math.random() * self.speed_m + self.speed_a) * (Math.floor(Math.random() * self.speed_m) || -1)
};
self.items.push( item );
});
console.log( 'Items: ', self.items );
window.requestAnimationFrame( self.update );
},
draw: function() {
const self = window.kpBouncer;
self.ctx.clearRect( 0, 0, self.canvas.width, self.canvas.height );
self.items.map( function( item ) {
const axis_x = ( item.x + .5 * item.width );
const axis_y = ( item.y + .5 * item.height );
self.ctx.save();
self.ctx.translate( axis_x, axis_y );
// self.ctx.rotate( item.rotate * Math.PI / 180 );
self.ctx.translate( -axis_x, -axis_y );
self.ctx.drawImage( item.el, item.x, item.y, item.width, item.height );
self.ctx.restore();
});
},
update: function() {
const self = window.kpBouncer;
window.requestAnimationFrame( self.update );
self.items = self.items.map( function( item ) {
// bottom bound / floor
if (item.y + item.height >= self.canvas.height) {
item.vel_y = -item.vel_y;
item.y = self.canvas.height - item.height;
}
// top bound / ceiling
if (item.y <= 0) {
item.vel_y = -item.vel_y;
item.y = 0;
}
// left bound
if (item.x <= 0) {
item.vel_x = -item.vel_x;
item.x = 0;
}
// right bound
if (item.x + item.width >= self.canvas.width) {
item.vel_x = -item.vel_x;
item.x = self.canvas.width - item.width;
}
// update item position
item.x += item.vel_x;
item.y += item.vel_y;
let rotate = ( self.speed_r + item.rotate );
if ( ( rotate < 0 ) || ( rotate > 359 ) ) {
rotate = 0; }
item.rotate = rotate;
return item;
});
self.draw();
},
canvas_click: function( ev ) {
const self = window.kpBouncer;
const mouse_x = ev.layerX;
const mouse_y = ev.layerY;
const item_clicked = self.items.find(function( item ) {
const left = ( item.x - item.width );
const right = ( item.x + item.width );
const top = ( item.y - item.height );
const bottom = ( item.y + item.height );
if ( mouse_x < left ) {
return false; }
if ( mouse_x > right ) {
return false; }
if ( mouse_y < top ) {
return false; }
if ( mouse_y > bottom ) {
return false; }
return item;
});
if ( !item_clicked ) {
return; }
const link = ( item_clicked.link || '' );
if ( link.length < 0 ) {
return; }
if ( !( link.startsWith( 'http' ) ) ) {
return; }
window.open( link, '_blank' );
},
canvas_hover: function( ev ) {
const self = window.kpBouncer;
// TODO: tidy up and place hover codes here
//
},
resize: function() {
const self = window.kpBouncer;
self.canvas.width = $( '#canvas' ).width();
self.canvas.height = $( '#canvas' ).height();
},
random: function( min, max ) {
const self = window.kpBouncer;
min = Math.ceil( min );
max = Math.floor( max );
return ( Math.floor( Math.random() * ( max - min + 1 ) ) + min );
},
random_bool: function() {
const self = window.kpBouncer;
const rand = self.random( 0, 1 );
return ( 0 === rand );
}
}
$(window).resize(function(){
bouncer.resize();
});
$( document ).ready( function() {
window.kpBouncer = bouncer;
bouncer.init();
});
// $(document).ready(function(){});
// $(window).resize(function(){});
// $(window).scroll(function(){});
} )( jQuery );
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
main {
position: relative;
width: 100vw;
height: 84vh;
background-color: red;
}
#canvas-box {
width: 100%;
height: 100%;
}
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#item-vault {
position: absolute;
top: 0;
left: 0;
width: 1px;
height: 1px;
opacity: 0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<main>
<div id="canvas-box">
<canvas id="canvas"></canvas>
</div>
<div id="item-vault">
<img
id="rw-cv-icon"
class="cv-icon rotating-icon"
src="https://uploads-ssl.webflow.com/60113be6489384599d9170bc/605b1211304c53283a43c330_Sticker---CV---112x78.png"
data-w="112"
data-h="68"
data-link="https://google.com/"
alt="CV Icon">
<img
id="rw-about-icon"
class="about-icon rotating-icon"
src="https://uploads-ssl.webflow.com/60113be6489384599d9170bc/605b121159d1b8b27d7447df_Sticker---About---162x76.png"
data-w="162"
data-h="76"
data-link="https://stackoverflow.com/"
alt="About Icon">
<img
id="rw-book-icon"
class="book-icon rotating-icon"
src="https://uploads-ssl.webflow.com/60113be6489384599d9170bc/605b12112d6624062f346a1a_Sticker---Book---153x68.png"
data-w="153"
data-h="68"
data-link="https://google.com"
alt="Book Icon">
</div>
</main>
解决方案
推荐阅读
- python - 将 Audioset ckpt 转换为 pb 文件
- c# - 获取数据库C#中的表总数
- javascript - 尝试在Javascript中比较不同数组中的对象
- java - 可执行 .jar 未运行 JavaFX - Ecliipse
- vb.net - 使用 IEnumerable 返回字符串的所有可能性
- java - turnRight 方法在组合锁程序中不起作用 - java
- c# - 从控制台应用程序创建/更新数据库模式
- javascript - jQuery.html() 函数不保留动态 DOM 中的选择和输入中的值
- python - 正则表达式 python - 仅当换行符后跟数字或特殊字符和空格时才匹配换行符
- swift - Swift IBDesignable UIButton 类 - 在 didRotate 上更改宽度