update
This commit is contained in:
parent
962caebbb7
commit
87bf53d076
1825 changed files with 94929 additions and 0 deletions
BIN
2-ui/5-widgets/6-widget-tasks/6-slider-events/slider.png
Executable file
BIN
2-ui/5-widgets/6-widget-tasks/6-slider-events/slider.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
29
2-ui/5-widgets/6-widget-tasks/6-slider-events/solution.md
Normal file
29
2-ui/5-widgets/6-widget-tasks/6-slider-events/solution.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Сопоставление значения и слайдера
|
||||
|
||||
Как сопоставить позицию слайдера и значение?
|
||||
|
||||
Для этого посмотрим крайние значения слайдера. Допустим, размер бегунка `10px`.
|
||||
|
||||
Раз центр соответствует значению, то крайнее левое значение будет соответствовать центру на `5px`, а крайнее правой -- центру на `5px` от правой границы:
|
||||
|
||||
<img src="slider.png">
|
||||
|
||||
Соответственно, ширина области изменения будет `sliderElem.clientWidth - thumbElem.clientWidth`. Далее её можно уже поделить на части, количество пикселей на значение будет:
|
||||
|
||||
```js
|
||||
pixelsPerValue = (sliderElem.clientWidth-thumbElem.clientWidth) / max;
|
||||
```
|
||||
|
||||
Может получиться так, что это значение будет дробным, меньше единицы. Например, если `max = 1000`, а ширина слайдера `110` (пробег 100), то будет `0.1` пикселя на значение.
|
||||
|
||||
Используя `pixelsPerValue` мы сможем переводить позицию бегунка в значение и обратно.
|
||||
|
||||
Крайнее левое значение `thumbElem.style.left` равно нулю, крайнее правой -- как раз ширине доступной области `sliderElem.clientWidth - thumbElem.clientWidth`. Поэтому можно получив значение, поделив его на `pixelsPerValue`:
|
||||
|
||||
```js
|
||||
value = Math.round( newLeft / pixelsPerValue);
|
||||
```
|
||||
|
||||
# Полное решение
|
||||
|
||||
[edit src="solution"/]
|
183
2-ui/5-widgets/6-widget-tasks/6-slider-events/solution.view/index.html
Executable file
183
2-ui/5-widgets/6-widget-tasks/6-slider-events/solution.view/index.html
Executable file
|
@ -0,0 +1,183 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="http://code.jquery.com/jquery.min.js"></script>
|
||||
<style>
|
||||
|
||||
.slider {
|
||||
width: 310px;
|
||||
height: 15px;
|
||||
margin: 5px;
|
||||
|
||||
border-radius: 5px;
|
||||
background: #E0E0E0;
|
||||
background: -moz-linear-gradient(left top , #E0E0E0, #EEEEEE) repeat scroll 0 0 transparent;
|
||||
background: -webkit-gradient(linear, left top, right bottom, from(#E0E0E0), to(#EEEEEE));
|
||||
background: linear-gradient(left top, #E0E0E0, #EEEEEE);
|
||||
}
|
||||
|
||||
.slider-thumb {
|
||||
position: relative;
|
||||
width: 10px;
|
||||
height: 25px;
|
||||
left: 10px;
|
||||
top: -5px;
|
||||
|
||||
border-radius: 3px;
|
||||
background: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sliding .slider-thumb {
|
||||
cursor: move;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="slider" class="slider">
|
||||
<div class="slider-thumb"></div>
|
||||
</div>
|
||||
|
||||
Slide:<span id="slide"> </span>
|
||||
Change:<span id="change"> </span>
|
||||
|
||||
<script>
|
||||
|
||||
function Slider(options) {
|
||||
var self = this;
|
||||
|
||||
var elem = options.elem;
|
||||
var thumbElem = elem.find('.slider-thumb');
|
||||
|
||||
// [<*>----------------]
|
||||
// |...............|
|
||||
// first last
|
||||
var pixelsPerValue = (elem.width() - thumbElem.width()) / options.max;
|
||||
var value = options.value || 0;
|
||||
|
||||
// при начале переноса фиксируются
|
||||
var thumbCursorShift; // сдвиг курсора относительно бегунка
|
||||
var sliderCoords; // и координаты слайдера
|
||||
|
||||
thumbElem.on('mousedown', onThumbMouseDown)
|
||||
.on('selectstart dragstart', false);
|
||||
|
||||
setSlidingValue(value, true);
|
||||
|
||||
|
||||
function onThumbMouseDown(e) {
|
||||
startSlide(e.pageX, e.pageY);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function onDocumentMouseMove(e) {
|
||||
// вычесть координату родителя, т.к. position: relative
|
||||
var newLeft = e.pageX - thumbCursorShift.x - sliderCoords.left;
|
||||
|
||||
// курсор ушёл вне слайдера
|
||||
if (newLeft < 0) {
|
||||
newLeft = 0;
|
||||
}
|
||||
|
||||
var rightEdge = elem.outerWidth() - thumbElem.outerWidth();
|
||||
if (newLeft > rightEdge) {
|
||||
newLeft = rightEdge;
|
||||
}
|
||||
|
||||
setSlidingValue( Math.round( newLeft / pixelsPerValue) );
|
||||
}
|
||||
|
||||
function onDocumentMouseUp() {
|
||||
endSlide();
|
||||
}
|
||||
|
||||
function endSlide() {
|
||||
$(document).off('.slider');
|
||||
$(self).triggerHandler({
|
||||
type: "change",
|
||||
value: value
|
||||
});
|
||||
|
||||
elem.removeClass('sliding');
|
||||
}
|
||||
|
||||
function startSlide(downPageX, downPageY) {
|
||||
var thumbCoords = thumbElem.offset();
|
||||
thumbCursorShift = {
|
||||
x: downPageX - thumbCoords.left,
|
||||
y: downPageY - thumbCoords.top
|
||||
};
|
||||
|
||||
sliderCoords = elem.offset();
|
||||
|
||||
$(document).on({
|
||||
'mousemove.slider': onDocumentMouseMove,
|
||||
'mouseup.slider': onDocumentMouseUp
|
||||
});
|
||||
|
||||
elem.addClass('sliding');
|
||||
}
|
||||
|
||||
/**
|
||||
* Установить промежуточное значение
|
||||
* quiet -- означает "не генерировать событие"
|
||||
*/
|
||||
function setSlidingValue(newValue, quiet) {
|
||||
value = newValue;
|
||||
|
||||
thumbElem.css('left', value * pixelsPerValue ^ 0);
|
||||
if (!quiet) {
|
||||
$(self).triggerHandler({
|
||||
type: "slide",
|
||||
value: value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Установить окончательное значение
|
||||
* @param {number} newValue новое значение
|
||||
* @param {boolean} quiet если установлен, то без события
|
||||
*/
|
||||
this.setValue = function(newValue, quiet) {
|
||||
// установить значение БЕЗ генерации события slide
|
||||
// т.е. slide в любом случае нет
|
||||
setSlidingValue(newValue, true);
|
||||
|
||||
// ..а change будет, если не указан quiet
|
||||
if (!quiet) {
|
||||
$(self).triggerHandler({
|
||||
type: "change",
|
||||
value: value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
var slider = new Slider({
|
||||
elem: $('#slider'),
|
||||
max: 100,
|
||||
value: 10
|
||||
});
|
||||
|
||||
$(slider).on({
|
||||
slide: function(e) {
|
||||
$('#slide').html(e.value);
|
||||
},
|
||||
change: function(e) {
|
||||
$('#change').html(e.value);
|
||||
}
|
||||
});
|
||||
|
||||
slider.setValue(50);
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
45
2-ui/5-widgets/6-widget-tasks/6-slider-events/task.md
Normal file
45
2-ui/5-widgets/6-widget-tasks/6-slider-events/task.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Слайдер с событиями
|
||||
|
||||
[importance 5]
|
||||
|
||||
На основе слайдера из задачи [](/task/slider) создайте графический компонент, который умеет возвращать/получать значение.
|
||||
|
||||
Синтаксис:
|
||||
|
||||
```js
|
||||
var slider = new Slider({
|
||||
elem: $('#slider'),
|
||||
max: 100 // слайдер на самой правой позиции соответствует 100
|
||||
});
|
||||
```
|
||||
|
||||
Метод `setValue` устанавливает значение:
|
||||
|
||||
```js
|
||||
slider.setValue(50);
|
||||
```
|
||||
|
||||
У слайдера должно быть два события: `slide` при каждом передвижении и `change` при отпускании мыши (установке значения).
|
||||
|
||||
Пример использования:
|
||||
|
||||
```js
|
||||
$(slider).on({
|
||||
slide: function(value) {
|
||||
$('#slide').html(value);
|
||||
},
|
||||
change: function(value) {
|
||||
$('#change').html(value);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
В действии:
|
||||
[iframe src="solution" height="60"]
|
||||
|
||||
<ul>
|
||||
<li>Дизайн слайдера, ширина/высота элементов должна быть изменяемой через CSS, без необходимости трогать JS-код.</li>
|
||||
<li>Центр бегунка должен располагаться над значением. Например, он должен быть в центре для 50 при максимуме 100.</li>
|
||||
</ul>
|
||||
|
||||
Исходный документ -- возьмите решение из задачи [](/task/slider).
|
Loading…
Add table
Add a link
Reference in a new issue