index.vue 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. <template>
  2. <div class="cl-scroll" ref="container" @wheel.prevent="handleScroll">
  3. <div class="scroll-wrapper" ref="wrapper" :style="{ left: left + 'px' }">
  4. <slot></slot>
  5. </div>
  6. </div>
  7. </template>
  8. <script>
  9. const padding = 15;
  10. export default {
  11. name: 'cl-scroll',
  12. data() {
  13. return {
  14. left: 0
  15. };
  16. },
  17. methods: {
  18. handleScroll(e) {
  19. const eventDelta = e.wheelDelta || -e.deltaY * 3;
  20. const $container = this.$refs.container;
  21. const $containerWidth = $container.offsetWidth;
  22. const $wrapper = this.$refs.wrapper;
  23. const $wrapperWidth = $wrapper.offsetWidth;
  24. if (eventDelta > 0) {
  25. this.left = Math.min(0, this.left + eventDelta);
  26. } else {
  27. if ($containerWidth - padding < $wrapperWidth) {
  28. if (this.left < -($wrapperWidth - $containerWidth + padding)) {
  29. this.left = this.left;
  30. } else {
  31. this.left = Math.max(
  32. this.left + eventDelta,
  33. $containerWidth - $wrapperWidth - padding
  34. );
  35. }
  36. } else {
  37. this.left = 0;
  38. }
  39. }
  40. },
  41. moveToTarget($target) {
  42. const $container = this.$refs.container;
  43. const $containerWidth = $container.offsetWidth;
  44. const $targetLeft = $target.offsetLeft;
  45. const $targetWidth = $target.offsetWidth;
  46. if ($targetLeft < -this.left) {
  47. // tag in the left
  48. this.left = -$targetLeft + padding;
  49. } else if (
  50. $targetLeft + padding > -this.left &&
  51. $targetLeft + $targetWidth < -this.left + $containerWidth - padding
  52. ) {
  53. // eslint-disable-next-line to ignore the next line.
  54. } else {
  55. // tag in the right
  56. this.left = -($targetLeft - ($containerWidth - $targetWidth) + padding);
  57. }
  58. }
  59. }
  60. };
  61. </script>
  62. <style lang="stylus" scoped>
  63. .cl-scroll {
  64. white-space: nowrap;
  65. position: relative;
  66. overflow: hidden;
  67. width: 100%;
  68. .scroll-wrapper {
  69. position: absolute;
  70. }
  71. }
  72. </style>