Перемещаем изображение по странице

Многие знают из программистов, а уж тем более из сайтостроителей, то для чего применяется CSS. Естественно основная его задача это отделение контента от дизайна. Но не будем углубляться в теорию, а посмотрим на это с другой стороны. А именно с той, как можно использовать CSS в паре с JavaScript. Мы по ходу данной статьи разберем пример того, как можно перемещать изображение прямо на странице. Но не все так просто, если брать во внимание кроссбраузерность (по крайней мере, с Internet Explorer и Opera). Вот Internet Explorer нам как раз и устроит сюрприз, но мы сделаем «финт ушами» и избавимся от него. Позже я расскажу, как в нашем случае обмануть Internet Explorer.

Для начала, создаем пустую html страницу. Сразу хочу отметить, что писать внешние скрипты и стили мы не будем, а будем все держать в одном месте. Хотя с профессиональной точки зрения это не правильно. И так создаем два стиля: один класс и один ID.

#screenshow {
	background: #FFF;
	border: 1px solid #000000;
	padding: 5px;
	position: absolute;
	z-index: 2;
	display: none;
}

.screenmoving {
	background: url(clear_background.html);
	position: absolute;
}

Далее в любом месте на странице (я предпочитаю в конце) размещаем DIV блок (вернее два, один вложен в другой).
Код выглядит вот так:

<div id="screenshow" style="text-align: justify;" ondblclick="hidescreen()" 
onmousedown="screendown(event)" onmouseup="screenup()"
onmousemove="screenmove(event)"></div>

Сразу хочу остановиться на моменте, почему мы не могли обойтись классом или одним ID, а потому что подругому пока не получается. Феномен. Ну а теперь осталось самое главное – это код на JavaScript. Открываем секцию

<script type="text/javascript" language="javascript"></script>

Сразу объявим две глобальные переменные:

var flag = false;   // Нажата ли клавиша мыши
var x,y;            // Координаты курсора мыши

Следующие две функции особо рассматривать не будем, просто напишите вот такой код:

function StrToInt(str) {
	var strbuf;
		strbuf = str.substr(0, str.indexOf("px"));
		return parseInt(strbuf, 10);
}

function getPageEventCoords(evt) {
  	var coords = {left: 0, top: 0};

  	if(evt.pageX) {
    		coords.left=evt.pageX;
    		coords.top=evt.pageY;
  	}
	else if (evt.clientX) {
    		coords.left=evt.clientX+document.body.scrollLeft-
                document.body.clientLeft;
    	        coords.top=evt.clientY+document.body.scrollTop-
                document.body.clientTop;

   		    if(document.body.parentElement &&
             document.body.parentElement.clientLeft){
      		    var bodParent = document.body.parentElement;
      		    coords.left+=bodParent.scrollLeft-bodParent.clientLeft;
     		    coords.top+=bodParent.scrollTop-bodParent.clientTop;
   		 }
 	 }
  return coords;
}

Единственное что можно сказать, так это то, что первая функция переводит строку в число, а вторая вычисляет координаты курсора мыши. Далее остались функции, которые собственно и будут осуществлять показ, скрывать и перемещать изображение. Для того чтобы продолжать дальше, нам необходимо работать с DIV блоками. Первый блок у нас имеет идентификатор – screenshow, а второй – screenmoving. Чтобы нам эти блоки найти, мы воспользуемся функцией getElementById, которая и находит элемент по его идентификатору. Далее сразу после нахождения элементов, необходимо определить координаты курсора мыши (именно в тот момент, когда вы нажали на ссылку). В функции showscreen, screenmove и screendown передается всего один параметр – evt. Атрибут event – обязателен. Собственно благодаря ему мы и определяем координаты курсора. Ну вот и первая функция, которая и отвечает за первоначальный показ изображения.

function showscreen(evt){
	var w = 400; // ширина изображения
	var h = 300; // высота изображения

	// идентификатор первого DIV блока
	var hl = document.getElementById('screenshow');
	// идентификатор второго DIV блока
	var ml = document.getElementById('screenmoving');
	// определение координат курсора мыши
	var coords = getPageEventCoords((evt)?evt:event);

	// позиция левого угла относительно оси x
	hl.style.left = (coords.left - w/4).toString()+'px';
	hl.style.width = w; // ширина
	hl.style.height = h; // высота
	// позиция левого угла относительно оси y
	hl.style.top = (coords.top).toString()+'px';

	// позиция левого угла относительно оси x
	ml.style.left = 0;
	ml.style.width = hl.style.width; // ширина
	ml.style.height = hl.style.height; // высота
	// позиция левого угла относительно оси y
	ml.style.top = 0;
	// восстанавливает блок с идентификатором «screenshow» на странице
	hl.style.display="block";
	// восстанавливает блок с идентификатором «screenmoving» на странице
	ml.style.display="block";
	// вставляем текст, который будет находиться в блоке
 	// с идентификатором «screenshow»
	hl.innerHTML = '
	<div id="screenmoving" class="screenmoving" style="display: block;
	left: 0px; width: 100%; top:0px; height:100%; text-align:justify;" 
	onmousemove="screenmove(event)"></div>' + screens[number];

}

Обратите внимание на то, что атрибуты стиля написаны заглавными буквами, это неспроста. По другому не выходит. Пришлось провести ряд экспериментов, но это уже другая история…

Далее идет функция, которая прячет DIV блоки и убирает их со страницы. Все довольно просто. Всего лишь в стилях двух блоков, атрибуту display присваивается значение none. И нашему флагу присваивается значение false.

function hidescreen() {
	// находим блок с идентификатором «screenmoving» и убираем его
	document.getElementById('screenmoving').style.display="none";
	// находим блок с идентификатором «screenshow» и убираем его
	document.getElementById('screenshow').style.display="none";
	flag = false; // деактивируем флаг
}

Далее идет функция screendown, которая обрабатывает нажатие кнопки мыши. Все что в ней происходит, так это то, что вычисляются координаты курсора мыши и флагу присваивается значение true, с таким значением флаг означает, что кнопка мыши нажата и удерживается.

function screendown(evt) {
	// находим блок с идентификатором screenshow
	var hl = document.getElementById('screenshow');
	// вычисляем координату x
	x = StrToInt(hl.style.left) - evt.clientX;
	// вычисляем координату y
	y = StrToInt(hl.style.top) - evt.clientY;
	flag = true; // активируем флаг
}

Далее идет функция screenup, которая обрабатывает событие при отпускании кнопки мыши.

function screenup() {
	// деактивируем флаг
	flag = false;
}

Ну вот, практически и все, осталось только рассмотреть последнюю функцию, которая собственно и осуществляет само перемещение изображения.

function screenmove(evt){
	// находим блок с идентификатором screenshow
	var hl = document.getElementById('screenshow');
	// определение координат курсора мыши
	var coords = getPageEventCoords((evt)?evt:event);
	var step = 1;

	// если нажата кнопка мыши
	if (flag == true)
		{
			hl.style.left = (evt.clientX + x).toString()+'px';
			hl.style.top = (evt.clientY + y).toString()+'px';
		}
}

Ну и последний шаг это вставить ссылку. В нашем случае это вот такой код:

<a onmousedown="showscreen(event)">Демонстрация</a>

Который в комментарии я думаю, не нуждается.
Теперь можете кликнуть по ссылке «демонстрация» и посмотреть что должно получиться в итоге.

Теперь из истории про обман IE

Дело в том, что можно было обойтись всего лишь одним блоком. Но в Internet Explorer такой способ не проходит. Так как получается, будто мы двигаем картинку. Но вот собственно мной был придуман следующий метод: создаем первый слой, на первом слое размещаем изображение, и на первом же слое размещаем второй слой, который по размеру делаем таким как и первый. Затем в качестве фона на втором слое устанавливаем несуществующую страницу формата html. В итоге он получается как бы прозрачным. Если фон не задавать вообще, то IE опять же не позволит двигать картинку. А если фон сделать какого нибудь цвета, то мы естественно не увидим самой картинки. Демо версию скачать можно здесь.