init
This commit is contained in:
parent
06f61d8ce8
commit
f301cb744d
2271 changed files with 103162 additions and 0 deletions
75
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution.md
Normal file
75
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
# CSS
|
||||
|
||||
Для захвата проще всего создать дополнительные `DIV'ы` и отпозиционировать их сбоку и справа-снизу `IMG`. При нажатии на них начинать смену размера.
|
||||
|
||||
CSS-структура:
|
||||
|
||||
```html
|
||||
<div class="resize-wrapper" style="width: 503px; height: 285px;">
|
||||
<img src="heroes.jpg" id="heroes" style="width:500px;height:282px">
|
||||
<div class="resize-handle-s"></div>
|
||||
<div class="resize-handle-e"></div>
|
||||
<div class="resize-handle-se"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
Внешний `DIV` подстраивается под размер картинки и имеет `position:relative`. Внутри него расположены абсолютно позиционированные "ручки" для захвата.
|
||||
|
||||
Стиль:
|
||||
|
||||
```css
|
||||
.resize-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.resize-wrapper img {
|
||||
/* img при таком DOCTYPE в некоторых браузерах имеет display:inline, в некоторых display:block
|
||||
если оставить inline, то под img браузер оставит пустое место для "хвостов" букв
|
||||
*/
|
||||
display: block;
|
||||
}
|
||||
|
||||
.resize-handle-se { /* правый-нижний угол */
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(handle-se.png) no-repeat;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.resize-handle-s { /* нижняя "рамка", за которую можно потащить */
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 3px;
|
||||
width:100%;
|
||||
background: gray;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.resize-handle-e { /* правая "рамка", за которую можно потащить */
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
height:100%;
|
||||
background: gray;
|
||||
cursor: e-resize;
|
||||
}
|
||||
```
|
||||
|
||||
Для обозначения низа используется буква "s" (south, "юг" по-английски), обозначения правой стороны -- буква "e" (east, "восток" по-английски).
|
||||
|
||||
Использование сторон света для обозначения направления можно часто встретить в скриптах.
|
||||
|
||||
# Алгоритм
|
||||
|
||||
<ol>
|
||||
<li>При инициализации IMG оборачивается во внешнюю обертку и обкладывается `DIV'ами`, на которых ловим `mousedown`. Обертка нужна, чтобы абсолютно позиционировать `DIV'ы` внутри неё под/сбоку изображения.</li>
|
||||
<li>При наступлении `mousedown`, начинаем ловить `document.mousemove` и подгонять картинку под размер, а обертку -- под картинку.
|
||||
|
||||
Желательно заодно отменить браузерное выделение и Drag'n'Drop, возвратив `false` из собработчиков событий `mousedown` и `dragstart`.
|
||||
</li>
|
||||
<li>При наступлении `mouseup` -- конец.</li>
|
||||
|
||||
[edit src="solution"]Открыть полное решение[/edit]
|
1
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution/.plnkr
Executable file
1
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"resizeable","plunk":"pJTYHHbuV5qUAMu3afMh"}
|
149
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution/index.html
Executable file
149
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution/index.html
Executable file
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="http://code.jquery.com/jquery.min.js"></script>
|
||||
<style>
|
||||
.resize-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.resize-wrapper img {
|
||||
/* img при таком DOCTYPE в некоторых браузерах имеет display:inline, в некоторых display:block
|
||||
если оставить inline, то под img браузер оставит пустое место для "хвостов" букв
|
||||
*/
|
||||
display: block;
|
||||
}
|
||||
|
||||
.resize-handle-se { /* правый-нижний угол */
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(http://js.cx/clipart/handle-se.png) no-repeat;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.resize-handle-s { /* нижняя "рамка", за которую можно потащить */
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 3px;
|
||||
width:100%;
|
||||
background: gray;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.resize-handle-e { /* правая "рамка", за которую можно потащить */
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
height:100%;
|
||||
background: gray;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<img style="width:500px;height:282px" id="heroes" src="http://js.cx/clipart/heroes.jpg">
|
||||
|
||||
<div id="info"></div>
|
||||
|
||||
<script>
|
||||
function Resizeable(options) {
|
||||
var self = this;
|
||||
|
||||
var elem = options.elem;
|
||||
var handleSize = options.handleSize || 3;
|
||||
|
||||
var newWidth, newHeight, resizeType; // размеры в процессе ресайза
|
||||
|
||||
// внешняя обертка
|
||||
var wrapper = $('<div class="resize-wrapper"/>')
|
||||
wrapper.prependTo(elem.parent())
|
||||
wrapper.append(elem);
|
||||
|
||||
// добавляем "ручки" в обертку
|
||||
wrapper.append(
|
||||
'<div class="resize-handle-s"/><div class="resize-handle-e"/><div class="resize-handle-se"/>'
|
||||
);
|
||||
|
||||
// отменить перенос и выделение браузера
|
||||
// в дополнение к return false из mousedown
|
||||
wrapper.on('selectstart dragstart', false);
|
||||
|
||||
adjustWrapperSize();
|
||||
|
||||
wrapper.on('mousedown', onMouseDown);
|
||||
|
||||
function onMouseDown(e) {
|
||||
var className = e.target.className;
|
||||
if (className.indexOf("resize-handle-") == 0) {
|
||||
// поймали клик на "ручке" - вызываем начало ресайза
|
||||
resizeType = className.slice("resize-handle-".length);
|
||||
startResize();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function adjustWrapperSize() {
|
||||
// подгоняет размер обертки под картинку
|
||||
wrapper.css({
|
||||
width: elem.width() + handleSize,
|
||||
height: elem.height() + handleSize
|
||||
});
|
||||
}
|
||||
|
||||
function startResize() {
|
||||
$(document).on('mousemove.resizeable', onDocumentMouseMove);
|
||||
$(document).on('mouseup.resizeable', onDocumentMouseUp);
|
||||
}
|
||||
|
||||
function onDocumentMouseMove(e) {
|
||||
var offset = wrapper.offset();
|
||||
|
||||
if (~resizeType.indexOf("s")) {
|
||||
// в ручке есть буква "s" - значит меняем высоту картинки
|
||||
newHeight = Math.max(e.pageY - offset.top, handleSize);
|
||||
elem.css('height', newHeight);
|
||||
}
|
||||
if (~resizeType.indexOf("e")) {
|
||||
// в ручке есть буква "e" - значит меняем ширину картинки
|
||||
newWidth = Math.max(e.pageX - offset.left, handleSize);
|
||||
elem.css('width', newWidth);
|
||||
}
|
||||
|
||||
// подогнать обертку
|
||||
adjustWrapperSize();
|
||||
}
|
||||
|
||||
function onDocumentMouseUp() {
|
||||
endResize();
|
||||
}
|
||||
|
||||
function endResize() {
|
||||
$(document).off('.resizeable');
|
||||
$(self).triggerHandler({
|
||||
type: "resize",
|
||||
newWidth: newWidth,
|
||||
newHeight: newHeight
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var resizeMe = new Resizeable({
|
||||
elem: $('#heroes')
|
||||
});
|
||||
|
||||
$(resizeMe).on("resize", function(e) {
|
||||
// вывести результат
|
||||
$('#info').html("ширина:" + e.newWidth + ", высота:" + e.newHeight);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
{"name":"resizeable","plunk":"pJTYHHbuV5qUAMu3afMh"}
|
149
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution/resizeable/index.html
Executable file
149
02-ui/05-widgets/06-widget-tasks/03-resize-img/solution/resizeable/index.html
Executable file
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="http://code.jquery.com/jquery.min.js"></script>
|
||||
<style>
|
||||
.resize-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.resize-wrapper img {
|
||||
/* img при таком DOCTYPE в некоторых браузерах имеет display:inline, в некоторых display:block
|
||||
если оставить inline, то под img браузер оставит пустое место для "хвостов" букв
|
||||
*/
|
||||
display: block;
|
||||
}
|
||||
|
||||
.resize-handle-se { /* правый-нижний угол */
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(http://js.cx/clipart/handle-se.png) no-repeat;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.resize-handle-s { /* нижняя "рамка", за которую можно потащить */
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 3px;
|
||||
width:100%;
|
||||
background: gray;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.resize-handle-e { /* правая "рамка", за которую можно потащить */
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
height:100%;
|
||||
background: gray;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<img style="width:500px;height:282px" id="heroes" src="http://js.cx/clipart/heroes.jpg">
|
||||
|
||||
<div id="info"></div>
|
||||
|
||||
<script>
|
||||
function Resizeable(options) {
|
||||
var self = this;
|
||||
|
||||
var elem = options.elem;
|
||||
var handleSize = options.handleSize || 3;
|
||||
|
||||
var newWidth, newHeight, resizeType; // размеры в процессе ресайза
|
||||
|
||||
// внешняя обертка
|
||||
var wrapper = $('<div class="resize-wrapper"/>')
|
||||
wrapper.prependTo(elem.parent())
|
||||
wrapper.append(elem);
|
||||
|
||||
// добавляем "ручки" в обертку
|
||||
wrapper.append(
|
||||
'<div class="resize-handle-s"/><div class="resize-handle-e"/><div class="resize-handle-se"/>'
|
||||
);
|
||||
|
||||
// отменить перенос и выделение браузера
|
||||
// в дополнение к return false из mousedown
|
||||
wrapper.on('selectstart dragstart', false);
|
||||
|
||||
adjustWrapperSize();
|
||||
|
||||
wrapper.on('mousedown', onMouseDown);
|
||||
|
||||
function onMouseDown(e) {
|
||||
var className = e.target.className;
|
||||
if (className.indexOf("resize-handle-") == 0) {
|
||||
// поймали клик на "ручке" - вызываем начало ресайза
|
||||
resizeType = className.slice("resize-handle-".length);
|
||||
startResize();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function adjustWrapperSize() {
|
||||
// подгоняет размер обертки под картинку
|
||||
wrapper.css({
|
||||
width: elem.width() + handleSize,
|
||||
height: elem.height() + handleSize
|
||||
});
|
||||
}
|
||||
|
||||
function startResize() {
|
||||
$(document).on('mousemove.resizeable', onDocumentMouseMove);
|
||||
$(document).on('mouseup.resizeable', onDocumentMouseUp);
|
||||
}
|
||||
|
||||
function onDocumentMouseMove(e) {
|
||||
var offset = wrapper.offset();
|
||||
|
||||
if (~resizeType.indexOf("s")) {
|
||||
// в ручке есть буква "s" - значит меняем высоту картинки
|
||||
newHeight = Math.max(e.pageY - offset.top, handleSize);
|
||||
elem.css('height', newHeight);
|
||||
}
|
||||
if (~resizeType.indexOf("e")) {
|
||||
// в ручке есть буква "e" - значит меняем ширину картинки
|
||||
newWidth = Math.max(e.pageX - offset.left, handleSize);
|
||||
elem.css('width', newWidth);
|
||||
}
|
||||
|
||||
// подогнать обертку
|
||||
adjustWrapperSize();
|
||||
}
|
||||
|
||||
function onDocumentMouseUp() {
|
||||
endResize();
|
||||
}
|
||||
|
||||
function endResize() {
|
||||
$(document).off('.resizeable');
|
||||
$(self).triggerHandler({
|
||||
type: "resize",
|
||||
newWidth: newWidth,
|
||||
newHeight: newHeight
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var resizeMe = new Resizeable({
|
||||
elem: $('#heroes')
|
||||
});
|
||||
|
||||
$(resizeMe).on("resize", function(e) {
|
||||
// вывести результат
|
||||
$('#info').html("ширина:" + e.newWidth + ", высота:" + e.newHeight);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
29
02-ui/05-widgets/06-widget-tasks/03-resize-img/task.md
Normal file
29
02-ui/05-widgets/06-widget-tasks/03-resize-img/task.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Менять размер картинки при помощи мыши
|
||||
|
||||
[importance 5]
|
||||
|
||||
Реализуйте интерфейс для смены размера изображения мышью.
|
||||
|
||||
Пусть изображение "тянется" при захвате его снизу, справа и в правом-нижнем углу, вот так:
|
||||
[iframe height=350 src="solution" link]
|
||||
|
||||
По окончанию смены размеров должно быть событие **`resize`** c новыми размерами.
|
||||
|
||||
Синтаксис:
|
||||
|
||||
```js
|
||||
var resizeMe = new Resizeable({
|
||||
elem: $('#heroes')
|
||||
});
|
||||
|
||||
$(resizeMe).on("resize", function(e) {
|
||||
// вывести результат
|
||||
$('#info').html("ширина:" + e.newWidth + ", высота:" + e.newHeight);
|
||||
});
|
||||
```
|
||||
|
||||
Минимальный размер изображения 3x3, меньше ресайзить нельзя.
|
||||
|
||||
В исходном документе есть ссылка на <a href="http://js.cx/clipart/handle-se.png">картинку handle-se.png</a> для правого-нижнего угла.
|
||||
|
||||
[edit src="task" task/]
|
1
02-ui/05-widgets/06-widget-tasks/03-resize-img/task/.plnkr
Executable file
1
02-ui/05-widgets/06-widget-tasks/03-resize-img/task/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"resizeable-src","plunk":"SMRJLzwRlYukmKwOxQWW"}
|
32
02-ui/05-widgets/06-widget-tasks/03-resize-img/task/index.html
Executable file
32
02-ui/05-widgets/06-widget-tasks/03-resize-img/task/index.html
Executable file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="http://code.jquery.com/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<img style="width:500px;height:282px" id="heroes" src="http://js.cx/clipart/heroes.jpg">
|
||||
|
||||
Картинка для декорации правого-нижнего угла: <img src="http://js.cx/clipart/handle-se.png">
|
||||
|
||||
<div id="info"></div>
|
||||
|
||||
<script>
|
||||
function Resizeable(options) {
|
||||
/* ваш код */
|
||||
}
|
||||
|
||||
var resizeMe = new Resizeable({
|
||||
elem: $('#heroes')
|
||||
});
|
||||
|
||||
$(resizeMe).on("resize", function(e) {
|
||||
// вывести результат
|
||||
$('#info').html("ширина:" + e.newWidth + ", высота:" + e.newHeight);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue