Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Помощь в реализации ползунка на svg

#javascript #html #css #svg


нужна помощь в реализации элемента интерфейса. Решил я реализовать 1 элемент, скрин
его вы увидите ниже, и что-то понятия не имею как такое реализуется. 
Начал писать на  и в принципе что-то получилось, но далекое от идеала. Итак, нужно
чтобы в месте где стоит синий ползунок и пересекаются обе линии, стоял ползунок способный
двигать их, т.е. если повернуть им влево, то красная полоса уменьшиться, а если вправо,
то уменьшиться зеленая, и увеличится другая, думаю вы поняли, и мне этот момент совершенно
непонятен, как такое можно реализовать? Объединить 2 ? Но как это сделать, чтобы на
них можно было воздействовать ползунком? 


Если это можно как-то реализовать не прибегая к svg буду очень рад помощи, если в
примере будет js и вам будет не сложно, то очень хотелось бы увидеть нативный, т.к.
изучаю его параллельно.

Мой код: 



.grey-cricle {
	-webkit-transform: rotate(-85deg) translate(-282px, 16px);
	-ms-transform: rotate(-85deg) translate(-282px, 16px);
	-o-transform: rotate(-85deg) translate(-282px, 16px);
	transform: rotate(-85deg) translate(-282px, 16px);
}
.new-game {
	width: 400px;
}

	100
	0
	
	
	
	
	99.99




    


Ответы

Ответ 1



На мой взгляд такие вещи нужно писать на фреймворках, но можно и на ванильном JS. Остались мелкие баги, но они устраняются уже элементарно и больше подвязаны к разметке svg. У нас есть 5 эвентов: на нажатие клавиши(только движок), на отжатие клавиши (вся область svg), покидание мышью области svg, и движение мыши. При клике мы вычисляем абсолютный центр надписи (нужно для определения угла). При движении мыши мы определяем текущий угол поворота регулятора и отрисовываем его в svg. Сделал еще параллельный event для обработки скрола мышкой или тачпадом - тоже удобно пользователю. Если есть вопросы по коду - спрашивайте. function bind(func, context) { return function() { // (*) return func.apply(context, arguments); }; } function getPos(el) { var rect = el.getBoundingClientRect(); console.log(rect); return { x: rect.left + rect.width / 2.0, y: rect.top + rect.height / 2.0 }; } var radius = parseFloat(stroker.getAttribute("r")); var curObj = { draggin: false, dragX: 0, dragY: 0, cent: { x: 0, y: 0 }, onMDTasker: function(evt) { this.draggin = true; this.cent = getPos(this.text); console.log(this.cent); this.dragX = evt.clientX; this.dragY = evt.clientY; this.dragFi = 2 * Math.PI / 100.0 * this.value * 0.98; return false; }, onMUTasker: function(evt) { this.draggin = false; return false; }, onMMTasker: function(evt) { if (this.draggin) { var curX = evt.clientX; var curY = evt.clientY; var deltaX = curX - this.cent.x; var deltaY = curY - this.cent.y; var Ksi = Math.atan2(deltaY, deltaX); var correctedKsi = Ksi + Math.PI / 2.0 * 0.98; if (correctedKsi < 0) { correctedKsi = correctedKsi + 2 * Math.PI; } var newVal = correctedKsi / 2 / Math.PI * 100.0 / 0.98; if (newVal < 0) { newVal = 0.0; } if (newVal > 100) { newVal = 100.0; } this.value = newVal; this.applyOutState(); } return false; }, onWheelEvent: function(evt) { var deltaY = evt.deltaY; var oldValue = parseFloat(this.text.innerHTML); var newValue = oldValue + deltaY / 10.0; if (newValue < 0) { newValue = 0.0; } if (newValue > 100) { newValue = 100.0; } this.value = newValue; this.applyOutState(); return false; }, svgE: document.getElementsByClassName("new-game")[0], value: 50.00, circLen: radius * 2 * Math.PI, applyOutState: function() { this.text.innerHTML = this.value.toFixed(2); var fi = 2 * Math.PI / 100.0 * this.value * 0.98; var circleArcLen = fi * radius; var empteArcLen = this.circLen - circleArcLen; this.stroker.setAttribute("stroke-dashoffset", "148"); this.stroker.setAttribute("stroke-dasharray", circleArcLen + " " + empteArcLen); this.tasker.setAttribute("cx", 150 + 95 * Math.cos(fi - Math.PI / 2.0 * 0.98)) this.tasker.setAttribute("cy", 150 + 95 * Math.sin(fi - Math.PI / 2.0 * 0.98)) } } curObj.onWheelEvent = bind(curObj.onWheelEvent, curObj); curObj.onMUTasker = bind(curObj.onMUTasker, curObj); curObj.onMDTasker = bind(curObj.onMDTasker, curObj); curObj.onMMTasker = bind(curObj.onMMTasker, curObj); curObj.svgE.addEventListener("wheel", curObj.onWheelEvent); curObj.text = document.getElementById("textVal"); curObj.stroker = document.getElementById("stroker"); curObj.tasker = document.getElementById("tasker"); curObj.tasker.addEventListener("mousedown", curObj.onMDTasker); curObj.svgE.addEventListener("mouseup", curObj.onMUTasker); curObj.svgE.addEventListener("mousemove", curObj.onMMTasker); curObj.svgE.addEventListener("mouseleave", curObj.onMUTasker); curObj.applyOutState(); 100 0 99.99

Ответ 2



Используетсья плагин RoundSlider Цвета правильные не смог подобрать но думаю такого примера впольне хватит. let fn1 = $.fn.roundSlider.prototype._setProperties; $.fn.roundSlider.prototype._setProperties = function () { fn1.apply(this); let o = this.options, r = o.radius, d = r * 2, r1 = r - (o.width / 2) - this._border(true), svgNS = "http://www.w3.org/2000/svg"; this._circum = Math.PI * (r1 * 2); let $svg = $(document.createElementNS(svgNS, "svg")); $svg.attr({ "height": d, "width": d }); this.$circle = $(document.createElementNS(svgNS, 'circle')).attr({ "fill": "transparent", "class": "rs-transition", "cx": r, "cy": r, "r": r1, "stroke-width": o.width - 2, "stroke-dasharray": this._circum }); let $path = this.$circle.clone().addClass("path-bg"); this._setDashOffset($path, this._end); // ####---- Добавление border ----#### let $border = this.$circle.clone().addClass("path-border").attr({ "stroke-width": o.width }); this._setDashOffset($border, this._end + 1.5); let $border_wrapper = $(document.createElementNS(svgNS, 'g')).css({ "transform-origin": "50% 50%", "transform": "rotate(-1deg)" }); $border_wrapper.append($border); $svg.append($border_wrapper, $path, this.$circle.addClass("range-bg")); this.$svg_box = $(document.createElement("div")).addClass("rs-transition rs-svg").append($svg).css({ "height": d, "width": d, "transform-origin": "50% 50%", "transform": "rotate(" + (o.startAngle + 180) + "deg)" }).appendTo(this.innerContainer); } $.fn.roundSlider.prototype._setDashOffset = function ($ele, deg) { let pct = (1 - (deg / 360)) * this._circum; $ele.css({ strokeDashoffset: pct }); } let fn2 = $.fn.roundSlider.prototype._changeSliderValue; $.fn.roundSlider.prototype._changeSliderValue = function (val, deg) { fn2.apply(this, arguments); deg = deg - this.options.startAngle; if (this._rangeSlider) { this.$svg_box.rsRotate(this._handle1.angle + 180); deg = this._handle2.angle - this._handle1.angle; } this._setDashOffset(this.$circle, deg); } /// настройки самого плагина /// $("#slider").roundSlider({ sliderType: "min-range", handleShape: "dot", radius: 110, startAngle: 95, endAngle: "+350", min: 3, max: 97, width: 16, handleSize: "+10", create: function (event) { this.control.find(".rs-handle").addClass("rs-transition").eq(0).rsRotate(-this._handle1.angle); } }).on("change drag", function (event) { $(event.handle.element).rsRotate(-event.handle.angle); }); $("#slider").roundSlider("option", "value", 50); .rs-border { border: none !important; } .rs-control .rs-range-color, .rs-control .rs-path-color, .rs-control .rs-bg-color { background-color: transparent; } .rs-control circle.path-bg { stroke: red; } .rs-control circle.range-bg { stroke: #81ce00; } .rs-control circle.path-border { stroke: #aaa; } .full .rs-tooltip { top: 50%; left: 50%; background: skyblue !important; color:#fff !important; border-radius:50%; } .rs-handle-dot:after { display: flex !important; content: "\f104 \f105" !important; font-family: FontAwesome !important; height: 100% !important; justify-content: space-around; padding: 5px !important; align-items: center !important; width: 100% !important; border-radius: 1000px; color: #fff !important; } .rs-handle-dot { background-color: skyblue !important; } .rs-handle-dot:after { background-color: skyblue !important; border:none !important; } .rs-handle-dot { border: none !important; padding: 0px !important; }


Комментариев нет:

Отправить комментарий