Flash облако с изображениями и текстом
Мы часто сталкиваемся на сайтах с такими модулями, как облако тегов. Обычно это либо текстовая информация, либо изображения. Понадобилось мне совместить эти варианты в один. Поискав в интернете, нашел одно более менее нормально решение — XML driven Flash Tag Cloud
Модуль хорош собой, но есть и некоторые недостатки, которые пришлось подправить, благо исходники автор прилагает.
Модуль довольно гибко настраивается через xml файл, вплоть до размера текста, его цвета. Проблема заключается в том, что изображение у нас масштабируется в зависимости от ширины текста, что не очень-то и удобно, т.к. задача была поставлена — вывести отдельно текст, отдельно изображение.
Поставленные задачи:
- Сделать независимый вывод изображений и текста
- Добавить возможность указания размера изображения
- Поправить проблемы с кодировкой, т.к. русский язык выводится не совсем правильно
- Убрать обводку при наведении мыши
- Разместить текст под изображением и оцентрировать его
Для всех манипуляций понадобится Macromedia Flash. Для начала скачиваем исходники модуля.
Для нормальной отладки открываем сам файл исходника source/text_and_image_cloud.fla и классы source/com/OneElement.as, source/com/ImageCloud.as
Честно говоря, с флэшем знаком на уровне выполнения простых лабораторных работ, но в разобраться довольно просто.
В ImageCloud.as нам особых изменений делать не нужно.
Для начала нам надо инициализировать считать значение высоты и ширины картинки из xml файла. Будем указывать их как атрибут iw для ширины и ih для высоты.
После строки:
1 | var image:String = ( node2["@rev"] == undefined ) ? ( "" ) : String( node2["@rev"] ); |
просто дописываем
1 2 | var iw:String = ( node2["@iw"] == undefined ) ? ( "" ) : String( node2["@iw"] ); var ih:String = ( node2["@ih"] == undefined ) ? ( "" ) : String( node2["@ih"] ); |
затем допишем эти параметры в инициализацию объекта класса OneElement:
1 | var mc:OneElement = new OneElement( node2, col, hicol, image, fontFace, iw, ih); |
переходим к файлу OneElement.as, в котором формируется блок текста с изображением. Ниже приведу весь листинг кода с моими комментариями для удобного ознакомления
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | //в список принимаемых параметров добавляем нашу ширину и высоту изображения public function OneElement( node:XML, color:Number, hicolor:Number, image:String, fontFace:String, iw:String, ih:String){ _node = node; _color = color; _hicolor = hicolor; _active = false; _image = image; _fontFace = fontFace; //присваиваем принятые параметры к ранее инициализированным переменным _iw = iw; _ih = ih; //здесь мы добавили условие. В случае, если текст отсутствует, то //просто не создаем текстовое поле. Заметьте, addChild(_tf); мы //перенесли вниз, для отображения текста под изображение if (_node){ // create the text field _tf = new TextField(); _tf.autoSize = TextFieldAutoSize.LEFT; _tf.selectable = false; // set styles var format:TextFormat = new TextFormat(); format.font = _fontFace; format.bold = true; format.color = color; //0xffffff; format.size = 2 * getNumberFromString( node["@style"] ); _tf.defaultTextFormat = format; _tf.embedFonts = true; // set text _tf.text = node; // scale and add _tf.x = -this.width / 2; _tf.y = -this.height / 2; } //удалив ниже строки, мы убрали обводку при наведении, но //спрайт _back мы все таки оставили, т.к. он используется для //позиционирования изображения и текста // create the back _back = new Sprite(); _back.x = -( _tf.textWidth/2 ) - 10; _back.y = -( _tf.textHeight/2 ) - 2; //start image loader //добавляем условие. Если изображение есть, то загружаем его. if (_image!=""){ var imageLoader:Loader = new Loader(); var imageRequest = new URLRequest(_image); imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete); imageLoader.load(imageRequest); } function onComplete(evt:Event) { var someImage:MovieClip = new MovieClip(); someImage.addChild(imageLoader.content); var scaleImg:Number = _back.width/someImage.width; //ранее высота и ширина изображения высчитывалась исходя из ширины текста //теперь, если у нас указаны высота или ширина, они применяются к изображению if (_iw != "") someImage.width = getNumberFromString(_iw); if (_ih != "") someImage.width = getNumberFromString(_ih); someImage.x = -someImage.width/2; someImage.y = (_back.height/2); addChild(someImage); //теперь нам надо изменить позиционирование текста. Если текст есть, то //задаем ему позицию по вертикали и горизонтали, тем самым центрируем и размещаем его //внизу изображения if(_tf) _tf.y = someImage.y + someImage.height + 5; if(_tf) _tf.x = someImage.x + (someImage.width/2) - (_tf.width/2); } // end image loader addChild(_tf); _back.visible = false; ... |
В исходнике из библиотеки можно удалить ненужные шрифты, что я и сделал, оставив только times new roman. А проблема с русским текстом решилась сама по себе после компиляции swf файла.
В итоге получаем вот такой модуль.
В примере внесены четыре объекта — текст, изображение, с измененными размерами, эта же картинка, но в оригинальном размере и векторное изображение.
Как видите, растровые изображения мерцают, избавиться от данного эффекта не получилось. Флэш нормально анимирует лишь векторные изображения, которое я добавил в качестве примера.
Так выглядит конфигурационный файл cloud_data.xml
1 2 3 4 5 6 | <tags> <a href="" style="font-size: 20pt;" color="0xccff00" hicolor="0x123456">тест русского языка</a> <a href="" style="font-size: 20px;" color="0x000000" iw="100" ih="50" rev="/wp-content/uploads/2011/09/1.jpg"></a> <a href="" style="font-size: 20px;" color="0x000000" rev="/wp-content/uploads/2011/09/1.jpg"></a> <a href="" style="font-size: 20px;" color="0x000000" rev="/wp-content/uploads/2011/09/3.swf"></a> </tags> |