悬停时更改画布内的图像

问题描述

我想在悬停状态下替换画布内的图像。棘手的部分是图像漂浮在容器内。

问题

如何在移动项悬停在画布内时运行函数

我尝试了什么

首先,我使用了 mouseentermousemoveonmousemove 函数来捕获悬停的项目。

当前问题

即使我可以在悬停状态捕获项目,它也无法正常工作。有时,当您在画布上移动光标时,即使光标超出其边界,它仍会记录一个项目。

注意事项

在当前版本中,没有可以交换的不同图像,我只是想先获取元素。唯一的变化(悬停状态)将是项目的背景颜色,所以我尝试使用内联 SVG(轻松更改 fill 属性),但内联 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,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>

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)