
只进行了基础的事件和布局,可优化的地方:luminance-box这个div加上后,由于和slider-run-way都是absolute定位,导致slider-run-way的点击事件无法设置值,只能通过滑块设置。暂时想不到咋处理,有想法可以讨论一下
- <div class="light-slider">
- <div
- class="slider-run-way"
- @click.stop="handleClickRunway($event)"
- ref="runwayRef"
- >
- <div class="active-bar" :style="{ width: activeWidth + '%' }">div>
- <div
- class="control-wrapper"
- :style="{ left: activeWidth + '%' }"
- @mousedown="handleMousedown($event)"
- >
- <div class="control-btn"><span>span><span>span>div>
- div>
- div>
- <div class="luminance-box" @click="handleRight">
- <img src="../../../../assets/home/homepage_control_bright.png" />
- <div class="right-box">
- <span class="num">{{ activeWidth }}%span>
- <span class="l-title">luminancespan>
- div>
- div>
- div>
- export default {
- name: "lightingControl",
- props: {
- isDisabled: {
- type: Boolean,
- default: true,
- },
- },
- data() {
- return {
- activeWidth: 13,
- runWayWidth: 0, // 滑道总宽度
- startX: 0,
- dragging: false,
- isClick: true,
- startPosition: 0,
- };
- },
- mounted() {
- this.$nextTick(() => {
- this.runWayWidth = this.$refs.runwayRef.clientWidth;
- });
- },
- methods: {
- handleClickRunway(e) {
- if (!this.isClick || this.isDisabled) return;
- console.log(e);
- const { runWayWidth } = this;
- const { offsetX } = e;
- const percent = parseInt((offsetX / runWayWidth) * 100);
- this.activeWidth = percent;
- },
- handleRight(e) {
- return false;
- },
- handleMousedown(e) {
- if (this.isDisabled) return;
- e.preventDefault();
- this.startX = e.clientX;
- this.onDragStart(e);
- window.addEventListener("mousemove", this.onDragging);
- window.addEventListener("mouseup", this.onDragEnd);
- },
- onDragStart(e) {
- this.dragging = true;
- this.isClick = true;
- this.startPosition = parseFloat(this.activeWidth);
- },
- onDragging(e) {
- e.stopPropagation();
- if (this.dragging) {
- this.isClick = false;
- let currentX = e.clientX;
- let diff = ((currentX - this.startX) / this.runWayWidth) * 100;
- this.newPosition = this.startPosition + diff;
- this.setPosition(this.newPosition);
- }
- },
- onDragEnd() {
- if (this.dragging) {
- setTimeout(() => {
- this.dragging = false;
- if (!this.isClick) {
- this.setPosition(this.newPosition);
- this.isClick = true;
- }
- }, 0);
- window.removeEventListener("mousemove", this.onDragging);
- window.removeEventListener("mouseup", this.onDragEnd);
- }
- },
- setPosition(newPosition) {
- if (newPosition < 0) {
- newPosition = 0;
- } else if (newPosition > 100) {
- newPosition = 100;
- }
- this.activeWidth = Math.round(newPosition);
- },
- },
- };
-
- .light-slider {
- margin-top: 16px;
- position: relative;
- .slider-run-way {
- width: 100%;
- position: relative;
- cursor: pointer;
- height: 70px;
- background: #d7eeff;
- border-radius: 4px 4px 4px 4px;
-
- .active-bar {
- height: 100%;
-
- position: absolute;
- left: 0;
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
- background: #36c1fd;
- }
- .control-wrapper {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 30px;
- width: 22px;
- position: absolute;
- user-select: none;
- z-index: 1001;
- top: 20px;
- transform: translateX(-50%);
- background-color: transparent;
- .control-btn {
- width: 16px;
- height: 24px;
- background: #fff;
- box-shadow: 0px 0px 5px 0px rgba(76, 115, 184, 0.5);
- border-radius: 2px 2px 2px 2px;
- color: #36c1fd;
- display: flex;
- align-items: center;
- justify-content: space-evenly;
- span {
- width: 2px;
- height: 6px;
- background: #36c1fd;
- border-radius: 30px 30px 30px 30px;
- }
- }
- }
- }
- .luminance-box {
- display: flex;
- width: 100%;
- height: 70px;
- justify-content: space-between;
- align-items: center;
- position: absolute;
- left: 0;
- top: 0;
-
- img {
- width: 20px;
- height: 20px;
- margin-left: 14px;
- }
- .l-title {
- font-size: 14px;
- }
- .right-box {
- color: #2e2e48;
- display: flex;
- flex-direction: column;
- align-items: center;
- font-weight: bolder;
- margin-right: 10px;
- .num {
- font-size: 24px;
- }
- }
- }
- }