OpenCart 2 — анимированная иконка мобильного меню — создаем модификатор
В данной статье мы рассмотрим как сделать анимированную иконку для мобильного меню в OpenCart. Такую иконку можно сделать, в принципе, для любого сайта, но в нашем случае подопытным станет магазин на OpenCart 2.х.
Вот так выглядит иконка мобильного меню по умолчанию.
Вот такой результат мы получим после внесения изменений.
Прежде всего мы должны понимать, что даже для такой мелочи, как изменение иконки, нам придется внести некоторые изменения в код магазина, и если мы это делаем в своем шаблоне (не в дефолтном), то нет проблем. Мы же будем делать иконку для дефолтного шаблона, поэтому, чтобы не вносить изменения напрямую, мы сделаем модификатор.
Берем шаблон модификатора, назовем его modification.ocmod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <modification> <code></code> <name></name> <version>1.0</version> <author></author> <link></link> <file path="catalog/controller/common/file.php"> <operation> <search><![CDATA[ ]]></search> <add position="replace|before|after"><![CDATA[ ]]></add> </operation> </file> </modification> |
и добавляем информацию: автора, название, версию, ссылку на разработчика:
- code — Menu-icon
- name — Menu-icon
- author — jul-collection.com
- link — https://jul-collection.com/
И в итоге код приобретает следующий вид:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <modification> <code>Menu-icon</code> <name>Menu-icon</name> <version>1.0</version> <author>jul-collection.com</author> <link>http://jul-collection.com/</link> <file path="catalog/controller/common/file.php"> <operation> <search><![CDATA[ ]]></search> <add position="replace|before|after"><![CDATA[ ]]></add> </operation> </file> </modification> |
Иконка мобильного меню выводится с помощью сервиса fontawesome.io в файле catalog/view/theme/default/template/common/header.tpl через класс .fa-bars. Если бы мы вносили изменения напрмую в код, то нам бы пришлось вносить их непосредственно в файл header.tpl, но поскольку в нашу задачу входит создание модификатора, то мы открываем именно его и меняем код. В строку, с указанием пути к файлу
1 |
<file path="catalog/controller/common/file.php"> |
добавляем путь к нужному файлу — header.tpl
1 |
<file path="catalog/view/theme/default/template/common/header.tpl"> |
Все то, что заключено в теги operation,
1 2 3 4 5 6 7 8 |
<operation> <search><![CDATA[ ]]></search> <add position="replace|before|after"><![CDATA[ ]]></add> </operation> |
меняем на
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<operation> <search><![CDATA[ <button type="button" class="btn btn-navbar navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"><i class="fa fa-bars"></i></button> ]]></search> <add position="replace"><![CDATA[ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="padding: 0px; margin-top: 10px;"> <div class="menu-icon"> <div class="line-1 no-animation"></div> <div class="line-2 no-animation"></div> <div class="line-3 no-animation"></div> </div> </button> ]]></add> </operation> |
Кроме того, что мы удаляем тег <i> и вставляем вместо него блок с классом menu-icon, мы еще и удаляем у элемента button классы btn и btn-navbar, а также дописываем style=»padding: 0px;», чтобы избавиться от бутстраповской обводки вокруг нашей будущей кнопки.
После всех этих манипуляций файл модификатора приобретает следующий вид:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?xml version="1.0" encoding="utf-8"?> <modification> <code>Menu-icon</code> <name>Menu-icon</name> <version>1.0</version> <author>jul-collection.com</author> <link>http://jul-collection.com/</link> <file path="catalog/view/theme/default/template/common/header.tpl"> <operation> <search><![CDATA[ <button type="button" class="btn btn-navbar navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"><i class="fa fa-bars"></i></button> ]]></search> <add position="replace"><![CDATA[ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="padding: 0px; margin-top: 10px;"> <div class="menu-icon"> <div class="line-1 no-animation"></div> <div class="line-2 no-animation"></div> <div class="line-3 no-animation"></div> </div> </button> ]]></add> </operation> </file> </modification> |
Затем нам нужно добавить стили оформления нашей кнопки. Указать размеры кнопки и анимацию. Данные стили можно изменить под свой дизайн. Создаем документ menu-icon.css и добавляем следующий код.
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
.menu-icon { cursor: pointer; z-index: 50; } .menu-icon .line-1, .menu-icon .line-2, .menu-icon .line-3 { height: 3px; width: 25px; background-color: #fff; } .menu-icon .line-1 { -webkit-animation: animate-line-1-rev .7s ease-in-out; animation: animate-line-1-rev .7s ease-in-out; } .menu-icon .line-2 { margin: 5px 0; -webkit-animation: animate-line-2-rev .7s ease-in-out; animation: animate-line-2-rev .7s ease-in-out; } .menu-icon .line-3 { -webkit-animation: animate-line-3-rev .7s ease-in-out; animation: animate-line-3-rev .7s ease-in-out; } .menu-icon:hover .line-1, .menu-icon:hover .line-2, .menu-icon:hover .line-3 { background-color: #fff; } .menu-icon.active .line-1, .menu-icon.active .line-2, .menu-icon.active .line-3 { background-color: #fff; } .menu-icon.active .line-1 { -webkit-animation: animate-line-1 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; animation: animate-line-1 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; } .menu-icon.active .line-2 { -webkit-animation: animate-line-2 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; animation: animate-line-2 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; } .menu-icon.active .line-3 { -webkit-animation: animate-line-3 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; animation: animate-line-3 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; } .no-animation { -webkit-animation: none !important; animation: none !important; } @-webkit-keyframes animate-line-1 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, 8px, 0) rotate(0); transform: translate3d(0, 8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 8px, 0) rotate(45deg); transform: translate3d(0, 8px, 0) rotate(45deg); } } @keyframes animate-line-1 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, 8px, 0) rotate(0); transform: translate3d(0, 8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 8px, 0) rotate(45deg); transform: translate3d(0, 8px, 0) rotate(45deg); } } @-webkit-keyframes animate-line-2 { 0% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } 100% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } } @keyframes animate-line-2 { 0% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } 100% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } } @-webkit-keyframes animate-line-3 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, -8px, 0) rotate(0); transform: translate3d(0, -8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, -8px, 0) rotate(135deg); transform: translate3d(0, -8px, 0) rotate(135deg); } } @keyframes animate-line-3 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, -8px, 0) rotate(0); transform: translate3d(0, -8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, -8px, 0) rotate(135deg); transform: translate3d(0, -8px, 0) rotate(135deg); } } @-webkit-keyframes animate-line-1-rev { 0% { -webkit-transform: translate3d(0, 8px, 0) rotate(45deg); transform: translate3d(0, 8px, 0) rotate(45deg); } 50% { -webkit-transform: translate3d(0, 8px, 0) rotate(0); transform: translate3d(0, 8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } @keyframes animate-line-1-rev { 0% { -webkit-transform: translate3d(0, 8px, 0) rotate(45deg); transform: translate3d(0, 8px, 0) rotate(45deg); } 50% { -webkit-transform: translate3d(0, 8px, 0) rotate(0); transform: translate3d(0, 8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } @-webkit-keyframes animate-line-2-rev { 0% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } 100% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } } @keyframes animate-line-2-rev { 0% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } 100% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } } @-webkit-keyframes animate-line-3-rev { 0% { -webkit-transform: translate3d(0, -8px, 0) rotate(135deg); transform: translate3d(0, -8px, 0) rotate(135deg); } 50% { -webkit-transform: translate3d(0, -8px, 0) rotate(0); transform: translate3d(0, -8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } @keyframes animate-line-3-rev { 0% { -webkit-transform: translate3d(0, -8px, 0) rotate(135deg); transform: translate3d(0, -8px, 0) rotate(135deg); } 50% { -webkit-transform: translate3d(0, -8px, 0) rotate(0); transform: translate3d(0, -8px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } |
На данный момент у нас получилась вот такая кнопка.
Следующий шаг — это повесить на нашу кнопку событие click, чтобы по клику мышки происходила анимация, описанная нами в css документе. Создаем файл menu-icon.js и размещаем в нем код:
1 2 3 4 5 6 |
$(document).ready(function() { $('.menu-icon').on('click', function() { $(this).toggleClass('active'); $(this).find('div').removeClass('no-animation'); }); }); |
На данном этапе мы имеем:
- файл модификатора — modification.ocmod
- документ со стилями — menu-icon.css
- документ со скриптом — menu-icon.js
Теперь мы создаем следующие папки (структура матрешки, т. е. папку в папке) — catalog > view > theme > default > template > default > stylesheet. В папку stylesheet помещаем файл со стилями (menu-icon.css).
В папке view создаем еще одну папку — javascript (теперь в папке view есть две папки — theme и javascript). В папку javascript помещаем js файл (menu-icon.js).
Осталось в модификаторе прописать подключение js и css файлов. Размещаем этот код после закрывающего тега operation, внутри которого мы создавали вывод новой кнопки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<operation> <search><![CDATA[ <link href="catalog/view/theme/default/stylesheet/stylesheet.css" rel="stylesheet"> ]]></search> <add position="after"><![CDATA[ <link href="catalog/view/theme/default/stylesheet/menu-icon.css" rel="stylesheet"> ]]></add> </operation> <operation> <search><![CDATA[ <script src="catalog/view/javascript/common.js" type="text/javascript"></script> ]]></search> <add position="after"><![CDATA[ <script src="catalog/view/javascript/menu-icon.js"></script> ]]></add> </operation> |
И получаем полностью готовый к использованию modification.ocmod
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 |
<?xml version="1.0" encoding="utf-8"?> <modification> <code>Menu-icon</code> <name>Menu-icon</name> <version>1.0</version> <author>jul-collection.com</author> <link>http://jul-collection.com/</link> <file path="catalog/view/theme/default/template/common/header.tpl"> <operation> <search><![CDATA[ <button type="button" class="btn btn-navbar navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"><i class="fa fa-bars"></i></button> ]]></search> <add position="replace"><![CDATA[ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="padding: 0px; margin-top: 10px;"> <div class="menu-icon"> <div class="line-1 no-animation"></div> <div class="line-2 no-animation"></div> <div class="line-3 no-animation"></div> </div> </button> ]]></add> </operation> <operation> <search><![CDATA[ <link href="catalog/view/theme/default/stylesheet/stylesheet.css" rel="stylesheet"> ]]></search> <add position="after"><![CDATA[ <link href="catalog/view/theme/default/stylesheet/menu-icon.css" rel="stylesheet"> ]]></add> </operation> <operation> <search><![CDATA[ <script src="catalog/view/javascript/common.js" type="text/javascript"></script> ]]></search> <add position="after"><![CDATA[ <script src="catalog/view/javascript/menu-icon.js"></script> ]]></add> </operation> </file> </modification> |
Для того, чтобы наша кнопка преобразилась, загружаем созданные нами файлы. Делать это по одному нет надобности, так как все файлы находятся в папке catalog, вот ее то и загружаем в корень магазина. Затем переходим в админку — Расширения — Установка расширений и устанавливаем наш модификатор. Не забываем обновить кэш модификатора в Расширения — Модификаторы. Заходим в магазин с мобильного устройства и любуемся анимированной кнопкой.