├── Image ├── pic_sutter.png ├── sample.gif ├── sample0.gif ├── sample1.png ├── sample2.png ├── sample3.png ├── sample4.png ├── sample5.png └── sample6.gif ├── README.en.md ├── README.md ├── dist ├── art.png ├── art1.png ├── art3.png ├── art4.png ├── art_city.png ├── frame_win1.png ├── frame_win1_2.png ├── frame_win2.png ├── frame_window.png ├── liteblue.png ├── litegreen.png ├── outside_window.png ├── outside_window1.png ├── outside_window2.png ├── outside_window3.png ├── outside_window4.png ├── outside_window5.png ├── outwin1.png ├── outwin2.png ├── outwin3.png ├── pic-shutter-card.js ├── pic_balcon_l.png ├── pic_balcon_r.png ├── purple.png ├── sample.gif ├── sample1.png ├── sample2.png ├── sample3.png ├── sample4.png ├── sample5.png ├── sc_shutter_bottom.png └── sc_shutter_slide.png └── hacs.json /Image/pic_sutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/pic_sutter.png -------------------------------------------------------------------------------- /Image/sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample.gif -------------------------------------------------------------------------------- /Image/sample0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample0.gif -------------------------------------------------------------------------------- /Image/sample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample1.png -------------------------------------------------------------------------------- /Image/sample2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample2.png -------------------------------------------------------------------------------- /Image/sample3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample3.png -------------------------------------------------------------------------------- /Image/sample4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample4.png -------------------------------------------------------------------------------- /Image/sample5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample5.png -------------------------------------------------------------------------------- /Image/sample6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/Image/sample6.gif -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # pic-shutter-card 2 | [![EN](https://img.shields.io/badge/lang-RU-green.svg)](/README.md) 3 | 4 | [![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg)](https://github.com/custom-components/hacs) 5 | ![](https://img.shields.io/github/watchers/samoswall/pic-shutter-card.svg) 6 | ![](https://img.shields.io/github/stars/samoswall/pic-shutter-card.svg) 7 | 8 | [![Donate](https://img.shields.io/badge/donate-Yandex-red.svg)](https://yoomoney.ru/fundraise/b8GYBARCVRE.230309) 9 | 10 | **Curtain Card for Lovelace UI Home Assistant** 11 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample.gif) 12 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample0.gif) 13 | **The card displays the current position of the curtain, allows you to control its position and has user settings for adjusting arbitrary images of the window, the view outside the window and the curtain canvas.** 14 | 15 | ## Content 16 | - [Adding a repository](#A1) 17 | - [Installation](#A2) 18 | - [Configuration](#A3) 19 | - [Description of image files](#A4) 20 | - [Sample Card code](#A5) 21 | - [Thanks](#A6) 22 | - [Donations](#A7) 23 | 24 | 25 | ## Adding a repository 26 | 27 | In the HACKS section, in the menu located in the upper right corner, select the item: **User repositories**. 28 | 29 | Enter the repository address: `https://github.com/samoswall/pic-shutter-card `, select the category **Lovelace**, click the **Add** button. 30 | 31 | 32 | ## Installation 33 | 34 | In the HACS section in the search, enter **pic-shutter-card**, select the card, click the **Download** button. 35 | 36 | 37 | ## Configuration 38 | 39 | ### General 40 | 41 | | Name | Type | Required | Default value | Description 42 | | ---- | ---- | -------- | ------- | ----------- 43 | | type | string | true | - | Must be "custom:pic-shutter-card" 44 | | title | string | false | - | The name of the card. It is displayed in the upper right corner. 45 | 46 | ### Параметры 47 | 48 | | Name | Type | Required | Default value | Description 49 | | ---- | ---- | --------------- | ------- | ----------- 50 | | entity | string | true | - | The shutter entity ID 51 | | name | string | false | Friendly name of the entity | Name to display for the shutter 52 | | buttons_position | string | false | `left` | Set buttons on `left` or on `right` of the shutter or `not show` to disable visibility 53 | | title_position | string | false | `top` | Set title on `top` or on `bottom` of the shutter 54 | | outside_window | string | false | `not show` | Set it to `show` for visibility of the background picture outside the window 55 | | invert_percentage | boolean | false | `false` | Set it to `true` if your shutter is 100% when it is closed, and 0% when it is opened 56 | | outside_window_pic | string | false | `/local/community/pic-shutter-card/outside_window.png` | The image file of the view outside the window. Uploaded with a card: `outside_window.png` `outside_window1.png` `outside_window2.png` `outside_window3.png` `outside_window4.png` `outside_window5.png` `outwin1.png` `outwin2.png` `outwin3.png ` 57 | | frame_window_pic | string | false | `/local/community/pic-shutter-card/frame_window.png` | The image file of the window frame. Uploaded with a card: `frame_window.png` `frame_win1.png` `frame_win1_2.png` `frame_win2.png` 58 | | shutter_slide_pic | string | false | `/local/community/pic-shutter-card/sc_shutter_slide.png` | The image file of the curtain cloth. Uploaded with a card: `art.png` `art1.png` `art_city.png` `art3.png` `art4.png` `purple.png` `liteblue.png` `litegreen.png` `sc_shutter_slide.png` 59 | | shutter_bottom_pic | string | false | `/local/community/pic-shutter-card/sc_shutter_bottom.png` | An image file of the bottom bar of the roller blinds. Uploaded with a card: `sc_shutter_bottom.png` 60 | | shutter_min_position | int (px)| false | 4 | The minimum position of the curtain. (in the open position) 61 | | shutter_max_position | int (px)| false | 127 | The maximum position of the curtain. (in the closed position) 62 | | shutter_heigth | int (px)| false | 140 | The height of the curtain. It is used only for curtains with an opening direction to the left and/or right. 63 | | shutter_direction | string | false | `up` | The direction of opening the curtain: up - `up`, left - `left` , right - `right` , left and right at the same time - `leftright` 64 | | shutter_top | int (px)| false | 17 | The indentation from the upper edge of the window to the curtain cloth. The value in pixels. (window height 141 pixels) 65 | | shutter_animation | string | false | `show` | Displaying the animation of the direction of movement: show - `show` , do not show - any other value 66 | | shutter_pic_height | int (px)| false | 155 | The height of the window image. Increases the vertical size of the card. 67 | | shutter_left | int (%) | false | 5 | The indentation of the curtain cloth from the left edge of the window. It is specified as a % of the window size. 68 | | shutter_width | int (%) | false | 90 | The width of the curtain cloth. It is specified as a % of the window size. 69 | | shutter_end_offset | int (%) | false | 0 | The offset of the lower value of the curtain cloth. Specified in % of 100. (Example: If at 80% the curtain completely covers the window, then offset 20 will display as 100% closed) 70 | | replace_0_percent | string | false | notuse | Replaces the value of 0% with a custom word. For example: Closed, Bottom, etc. Any language is allowed. 71 | | replace_100_percent | string | false | notuse | Replaces the value of 100% with a custom word. For example: Open, Top, etc. Any language is allowed. 72 | 73 | 74 | ### Description of image files 75 | 76 | There are already some images in the `pic-shutter-card` folder: 77 | 78 | | File | Description | Image Size | Image 79 | | ---- | ----------- | ----------- | -------- 80 | | frame_window.png | Window frame option 1 (vertical blinds) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_window.png) 81 | | frame_win1.png | Window frame option 2 (white frame with window sill) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_win1.png) 82 | | frame_win1_2.png | Window frame option 2 with curtain cloth art4.png | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_win1_2.png) 83 | | frame_win2.png | Window frame option 3 (brown frame) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_win2.png) 84 | | outside_window.png | Image of the view outside the window option 1 (Moscow City) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window.png) 85 | | outside_window1.png | Image of the view outside the window option 2 (Panorama of the night city part 1) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window1.png) 86 | | outside_window2.png | Image of the view outside the window option 2 (Panorama of the night city part 2) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window2.png) 87 | | outside_window3.png | Image of the view outside the window option 2 (Panorama of the night city part 3) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window3.png) 88 | | outside_window4.png | Image of the view outside the window option 2 (Panorama of the night city part 4) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window4.png) 89 | | outside_window5.png | Image of the view outside the window option 2 (Panorama of the night city part 5) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window5.png) 90 | | outwin1.png | Image of the view outside the window option 3 (Nature) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outwin1.png) 91 | | outwin2.png | Image of the view outside the window option 4 (Forest) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outwin2.png) 92 | | outwin3.png | Image of the view outside the window option 5 (Lake) | (153px x 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outwin3.png) 93 | | art.png | Curtain canvas image option 1 (Abstraction white background) | (100px x 150px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art.png) 94 | | art1.png | Curtain canvas image option 2 (Abstraction black background) | (141px x 125px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art1.png) 95 | | art_city.png | Canvas curtain image option 3 (Night City black background) | (141px x 125px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art_city.png) 96 | | art3.png | Curtain canvas image option 1 (Abstraction white background) | (142px x 145px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art3.png) 97 | | art4.png | Picture of the curtain cloth option 4 (Blue curtain on the curtain) | (141px x 130px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art4.png) 98 | | purple.png | Image of a purple curtain cloth | (1px x 1px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/purple.png) 99 | | liteblue.png | Image of a blue curtain cloth | (1px x 1px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/liteblue.png) 100 | | litegreen.png | Image of a light green curtain cloth | (1px x 1px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/litegreen.png) 101 | | sc_shutter_slide.png | Louver image (top 4 pixels white, bottom with transparent gradient) | (1px x 6px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/sc_shutter_slide.png) 102 | | sc_shutter_bottom.png | Image of the bottom bar of the roller blinds | (137px x 7px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/sc_shutter_bottom.png) 103 | | pic_balcon_l.png | Window frame with door. (left) | (232px x 610px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/pic_balcon_l.png) 104 | | pic_balcon_r.png | Window frame with door. (right) | (234px x 610px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/pic_balcon_r.png) 105 | 106 | 107 | ### Examples of the card code 108 | 109 | **Example of the minimum card code** 110 | 111 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample1.png) 112 | ```yaml 113 | type: custom:pic-shutter-card 114 | entities: 115 | - entity: cover.roll_1 116 | ``` 117 | 118 | **Sample card code 1** 119 | 120 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample2.png) 121 | ```yaml 122 | type: horizontal-stack 123 | cards: 124 | - type: custom:pic-shutter-card 125 | entities: 126 | - entity: cover.roll_2 127 | name: ' ' 128 | buttons_position: not show 129 | title_position: bottom 130 | outside_window: show 131 | outside_window_pic: /local/community/pic-shutter-card/outwin1.png 132 | shutter_slide_pic: /local/community/pic-shutter-card/sc_shutter_slide.png 133 | shutter_animation: not show 134 | - type: custom:pic-shutter-card 135 | entities: 136 | - entity: cover.roll_2 137 | name: ' ' 138 | buttons_position: not show 139 | title_position: bottom 140 | outside_window: show 141 | outside_window_pic: /local/community/pic-shutter-card/outwin2.png 142 | shutter_slide_pic: /local/community/pic-shutter-card/purple.png 143 | - type: custom:pic-shutter-card 144 | entities: 145 | - entity: cover.roll_2 146 | name: ' ' 147 | buttons_position: not show 148 | title_position: bottom 149 | outside_window: show 150 | outside_window_pic: /local/community/pic-shutter-card/outwin1.png 151 | shutter_slide_pic: /local/community/pic-shutter-card/litegreen.png 152 | - type: custom:pic-shutter-card 153 | entities: 154 | - entity: cover.roll_2 155 | name: ' ' 156 | buttons_position: not show 157 | title_position: bottom 158 | outside_window: show 159 | outside_window_pic: /local/community/pic-shutter-card/outwin2.png 160 | shutter_slide_pic: /local/community/pic-shutter-card/liteblue.png 161 | shutter_animation: not show 162 | ``` 163 | 164 | **Sample card code 2** 165 | 166 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample3.png) 167 | ```yaml 168 | type: horizontal-stack 169 | cards: 170 | - type: custom:pic-shutter-card 171 | entities: 172 | - entity: cover.roll_1 173 | name: Left 174 | buttons_position: left 175 | title_position: bottom 176 | outside_window: show 177 | outside_window_pic: /local/community/pic-shutter-card/outside_window2.png 178 | frame_window_pic: /local/community/pic-shutter-card/frame_window.png 179 | shutter_slide_pic: /local/community/pic-shutter-card/art1.png 180 | shutter_bottom_pic: none 181 | shutter_direction: left 182 | shutter_heigth: 135 183 | shutter_min_position: 5 184 | shutter_max_position: 95 185 | shutter_animation: show 186 | - type: custom:pic-shutter-card 187 | entities: 188 | - entity: cover.roll_1 189 | name: LeftRight 190 | buttons_position: left 191 | title_position: bottom 192 | outside_window: show 193 | outside_window_pic: /local/community/pic-shutter-card/outside_window4.png 194 | frame_window_pic: /local/community/pic-shutter-card/frame_window.png 195 | shutter_slide_pic: /local/community/pic-shutter-card/art1.png 196 | shutter_bottom_pic: none 197 | shutter_direction: leftright 198 | shutter_heigth: 135 199 | shutter_min_position: 5 200 | shutter_max_position: 95 201 | shutter_animation: show 202 | - type: custom:pic-shutter-card 203 | entities: 204 | - entity: cover.roll_1 205 | name: Right 206 | buttons_position: left 207 | title_position: bottom 208 | outside_window: show 209 | outside_window_pic: /local/community/pic-shutter-card/outside_window5.png 210 | frame_window_pic: /local/community/pic-shutter-card/frame_window.png 211 | shutter_slide_pic: /local/community/pic-shutter-card/art1.png 212 | shutter_bottom_pic: none 213 | shutter_direction: right 214 | shutter_heigth: 135 215 | shutter_min_position: 5 216 | shutter_max_position: 95 217 | shutter_animation: show 218 | ``` 219 | 220 | **Sample card code 3** 221 | 222 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample4.png) 223 | ```yaml 224 | type: horizontal-stack 225 | cards: 226 | - type: custom:pic-shutter-card 227 | entities: 228 | - entity: cover.roll_1 229 | name: Left 230 | buttons_position: right 231 | title_position: bottom 232 | shutter_animation: show 233 | shutter_min_position: 5 234 | shutter_top: 4 235 | shutter_max_position: 135 236 | outside_window: show 237 | outside_window_pic: /local/community/pic-shutter-card/outside_window.png 238 | frame_window_pic: /local/community/pic-shutter-card/frame_win1.png 239 | shutter_slide_pic: /local/community/pic-shutter-card/art_city.png 240 | shutter_bottom_pic: show 241 | - type: custom:pic-shutter-card 242 | entities: 243 | - entity: cover.roll_1 244 | name: Right 245 | buttons_position: left 246 | title_position: bottom 247 | shutter_animation: show 248 | outside_window: show 249 | outside_window_pic: /local/community/pic-shutter-card/outwin1.png 250 | frame_window_pic: /local/community/pic-shutter-card/frame_win1_2.png 251 | shutter_slide_pic: /local/community/pic-shutter-card/art4.png 252 | shutter_bottom_pic: none 253 | shutter_top: -1 254 | shutter_heigth: 159 255 | shutter_direction: leftright 256 | shutter_min_position: -1 257 | shutter_max_position: 100 258 | ``` 259 | 260 | **Sample card code 4** 261 | 262 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample5.png) 263 | ```yaml 264 | type: horizontal-stack 265 | cards: 266 | - type: custom:pic-shutter-card 267 | entities: 268 | - entity: cover.roll_2 269 | name: ' ' 270 | buttons_position: left 271 | title_position: bottom 272 | outside_window: show 273 | outside_window_pic: /local/community/pic-shutter-card/outside_window.png 274 | frame_window_pic: /local/community/pic-shutter-card/frame_win1.png 275 | shutter_min_position: 3 276 | shutter_top: 5 277 | shutter_max_position: 137 278 | - type: custom:pic-shutter-card 279 | entities: 280 | - entity: cover.roll_2 281 | name: ' ' 282 | buttons_position: right 283 | title_position: bottom 284 | outside_window: show 285 | outside_window_pic: /local/community/pic-shutter-card/outside_window.png 286 | frame_window_pic: /local/community/pic-shutter-card/frame_win2.png 287 | shutter_min_position: 3 288 | shutter_top: 5 289 | shutter_max_position: 142 290 | ``` 291 | 292 | **Sample card code 5** 293 | 294 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample6.gif) 295 | ```yaml 296 | type: horizontal-stack 297 | cards: 298 | - type: custom:pic-shutter-card 299 | entities: 300 | - entity: cover.roll_1 301 | name: ' ' 302 | buttons_position: left 303 | title_position: bottom 304 | outside_window: show 305 | frame_window_pic: /local/community/pic-shutter-card/pic_balcon_l.png 306 | shutter_min_position: 3 307 | shutter_top: 18 308 | shutter_left: 21 309 | shutter_max_position: 257 310 | shutter_pic_height: 300 311 | shutter_width: 74 312 | - type: custom:pic-shutter-card 313 | entities: 314 | - entity: cover.roll_2 315 | name: ' ' 316 | buttons_position: right 317 | title_position: bottom 318 | outside_window: show 319 | frame_window_pic: /local/community/pic-shutter-card/pic_balcon_r.png 320 | shutter_min_position: 3 321 | shutter_top: 18 322 | shutter_left: 3 323 | shutter_max_position: 173 324 | shutter_pic_height: 300 325 | shutter_width: 80 326 | ``` 327 | 328 | ### Thanks 329 | 330 | This card is an upgrade of the [has-shutter-card](https://github.com/Deejayfool/has-shutter-card). 331 | Thanks to the author [Deejayfool](https://github.com/Deejayfool). 332 | 333 | 334 | ## Donations 335 | You can support this or other projects. 336 | [![Donate](https://img.shields.io/badge/donate-Yandex-red.svg)](https://yoomoney.ru/fundraise/b8GYBARCVRE.230309) 337 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pic-shutter-card 2 | [![EN](https://img.shields.io/badge/lang-EN-green.svg)](/README.en.md) 3 | 4 | [![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg)](https://github.com/custom-components/hacs) 5 | ![](https://img.shields.io/github/watchers/samoswall/pic-shutter-card.svg) 6 | ![](https://img.shields.io/github/stars/samoswall/pic-shutter-card.svg) 7 | 8 | [![Donate](https://img.shields.io/badge/donate-Yandex-red.svg)](https://yoomoney.ru/fundraise/b8GYBARCVRE.230309) 9 | 10 | **Карточка штор для Lovelace UI Home Assistant** 11 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample.gif) 12 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample0.gif) 13 | **Карточка отображает текущее положение шторы, позволяет управлять её положением и имеет пользовательские настройки для устоновки произвольных изображений окна, вида за окном и полотна шторы.** 14 | 15 | ## Содержание 16 | - [Добавление репозитория](#A1) 17 | - [Установка](#A2) 18 | - [Конфигурация](#A3) 19 | - [Описание файлов изображений](#A4) 20 | - [Примеры кода карточки](#A5) 21 | - [Благодарности](#A6) 22 | - [Пожертвования](#A7) 23 | 24 | 25 | ## Добавление репозитория 26 | 27 | В разделе HACS в меню, расположенном в правом верхнем углу, выбираем пункт: **Пользовательские репозитории**. 28 | 29 | Вводим адрес репозитория: `https://github.com/samoswall/pic-shutter-card`, выбираем категорию **Lovelace**, нажимаем кнопку **Добавить**. 30 | 31 | 32 | ## Установка 33 | 34 | В разделе HACS в поиске вводим **pic-shutter-card**, выбираем карточку, нажимаем кнопку **Скачать**. 35 | 36 | 37 | ## Конфигурация 38 | 39 | ### Главное 40 | 41 | | Имя | Тип | Важность параметра | Значение по умолчанию | Описание 42 | | ---- | ---- | -------- | ------- | ----------- 43 | | type | string | Обязательно | - | Должно быть "custom:pic-shutter-card" 44 | | title | string | Не обязательно | - | Название карточки. Отображается в верхнем правом углу. 45 | 46 | ### Параметры 47 | 48 | | Имя | Тип | Важность параметра | Значение по умолчанию | Описание 49 | | ---- | ---- | --------------- | ------- | ----------- 50 | | entity | string | Обязательно | - | Идентификатор сущности 51 | | name | string | Не обязательно | Friendly name of the entity | Отображаемое имя шторы 52 | | buttons_position | string | Не обязательно | `left` | Местоположение кнопок управления: слева - `left` , справа - `right` от окна или не показывать - `not show` 53 | | title_position | string | Не обязательно | `top` | Местоположение имени шторы и процента открытия: сверху - `top` , снизу - `bottom` 54 | | outside_window | string | Не обязательно | `not show` | Отображение картинки вида за окном: показывать - `show` , не показывать - любое другое значение 55 | | invert_percentage | boolean | Не обязательно | `false` | Инверсия положения шторы. Установите `true` если 100% - штора закрыта и 0% when it is opened 56 | | outside_window_pic | string | Не обязательно | `/local/community/pic-shutter-card/outside_window.png` | Файл изображения вида за окном. Загружены с карточкой: `outside_window.png` `outside_window1.png` `outside_window2.png` `outside_window3.png` `outside_window4.png` `outside_window5.png` `outwin1.png` `outwin2.png` `outwin3.png ` 57 | | frame_window_pic | string | Не обязательно | `/local/community/pic-shutter-card/frame_window.png` | Файл изображения рамы окна. Загружены с карточкой: `frame_window.png` `frame_win1.png` `frame_win1_2.png` `frame_win2.png` 58 | | shutter_slide_pic | string | Не обязательно | `/local/community/pic-shutter-card/sc_shutter_slide.png` | Файл изображения полотна шторы. Загружены с карточкой: `art.png` `art1.png` `art_city.png` `art3.png` `art4.png` `purple.png` `liteblue.png` `litegreen.png` `sc_shutter_slide.png` 59 | | shutter_bottom_pic | string | Не обязательно | `/local/community/pic-shutter-card/sc_shutter_bottom.png` | Файл изображения нижней планки у рулонных штор. Загружен с карточкой: `sc_shutter_bottom.png` 60 | | shutter_min_position | int (px)| Не обязательно | 4 | Минимальное положение шторы. (в открытом положении) 61 | | shutter_max_position | int (px)| Не обязательно | 127 | Максимальное положение шторы. (в закрытом положении) 62 | | shutter_heigth | int (px)| Не обязательно | 140 | Высота шторы. Используется только для штор, у которых направление открытия влево и/или вправо. 63 | | shutter_direction | string | Не обязательно | `up` | Направление открытия шторы: вверх - `up` , влево - `left` , вправо - `right` , влево и вправо одновременно - `leftright` 64 | | shutter_top | int (px)| Не обязательно | 17 | Отступ от верхнего края окна до полотна шторы. Значение в пикселях. (высота окна 141 пиксель) 65 | | shutter_animation | string | Не обязательно | `show` | Отображение анимации направления движения: показывать - `show` , не показывать - любое другое значение 66 | | shutter_pic_height | int (px)| Не обязательно | 155 | Высота изображения окна. Увеличивает вертикальный размер карточки. 67 | | shutter_left | int (%) | Не обязательно | 5 | Отступ полотна шторы от левого края окна. Указывается в % от размера окна. 68 | | shutter_width | int (%) | Не обязательно | 90 | Ширина полотна шторы. Указывается в % от размера окна. 69 | | shutter_end_offset | int (%) | Не обязательно | 0 | Смещение нижнего значения полотна шторы. Указывается в % от 100. (Пример: Если при 80% штора полностью закрывает окно, то смещение 20 отобразит как закрытое на 100%) 70 | | replace_0_percent | string | Не обязательно | notuse | Заменяет значение 0% на пользовательское слово. Например: Закрыто, Опущено и т.д. 71 | | replace_100_percent | string | Не обязательно | notuse | Заменяет значение 100% на пользовательское слово. Например: Открыто, Поднято и т.д. 72 | 73 | 74 | ## Описание файлов изображений 75 | 76 | В папке карточки `pic-shutter-card` уже имеются некоторые изображения: 77 | 78 | | Файл | Описание | Размер изображения | Изображение 79 | | ---- | ----------- | ----------- | -------- 80 | | frame_window.png | Рама окна вариант 1 (вертикальные жалюзи) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_window.png) 81 | | frame_win1.png | Рама окна вариант 2 (белая рама с подоконником) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_win1.png) 82 | | frame_win1_2.png | Рама окна вариант 2 c гардиной для полотна шторы art4.png | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_win1_2.png) 83 | | frame_win2.png | Рама окна вариант 3 (коричневая рама) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/frame_win2.png) 84 | | outside_window.png | Изображение вида за окном вариант 1 (Москва Сити) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window.png) 85 | | outside_window1.png | Изображение вида за окном вариант 2 (Панорама ночного города часть 1) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window1.png) 86 | | outside_window2.png | Изображение вида за окном вариант 2 (Панорама ночного города часть 2) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window2.png) 87 | | outside_window3.png | Изображение вида за окном вариант 2 (Панорама ночного города часть 3) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window3.png) 88 | | outside_window4.png | Изображение вида за окном вариант 2 (Панорама ночного города часть 4) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window4.png) 89 | | outside_window5.png | Изображение вида за окном вариант 2 (Панорама ночного города часть 5) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outside_window5.png) 90 | | outwin1.png | Изображение вида за окном вариант 3 (Природа) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outwin1.png) 91 | | outwin2.png | Изображение вида за окном вариант 4 (Лес) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outwin2.png) 92 | | outwin3.png | Изображение вида за окном вариант 5 (Озеро) | (153px х 151px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/outwin3.png) 93 | | art.png | Изображение полотна шторы вариант 1 (Абстракция белый фон) | (100px х 150px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art.png) 94 | | art1.png | Изображение полотна шторы вариант 2 (Абстракция черный фон) | (141px х 125px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art1.png) 95 | | art_city.png | Изображение полотна шторы вариант 3 (Ночной город черный фон) | (141px х 125px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art_city.png) 96 | | art3.png | Изображение полотна шторы вариант 1 (Абстракция белый фон) | (142px х 145px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art3.png) 97 | | art4.png | Изображение полотна шторы вариант 4 (Синяя штора на гардине) | (141px х 130px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/art4.png) 98 | | purple.png | Изображение сиреневого полотна шторы | (1px х 1px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/purple.png) 99 | | liteblue.png | Изображение голубого полотна шторы | (1px х 1px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/liteblue.png) 100 | | litegreen.png | Изображение светлозеленого полотна шторы | (1px х 1px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/litegreen.png) 101 | | sc_shutter_slide.png | Изображение жалюзи (верхние 4 пикселя белые, нижние с прозрачным градиентом) | (1px х 6px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/sc_shutter_slide.png) 102 | | sc_shutter_bottom.png | Изображение нижней планки у рулонных штор | (137px х 7px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/sc_shutter_bottom.png) 103 | | pic_balcon_l.png | Рама окна с дверью. (левая) | (232px x 610px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/pic_balcon_l.png) 104 | | pic_balcon_r.png | Рама окна с дверью. (правая) | (234px x 610px) | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/dist/pic_balcon_r.png) 105 | 106 | 107 | ### Примеры кода карточки 108 | 109 | **Пример минимального кода карточки** 110 | 111 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample1.png) 112 | ```yaml 113 | type: custom:pic-shutter-card 114 | entities: 115 | - entity: cover.roll_1 116 | ``` 117 | 118 | **Пример кода карточки 1** 119 | 120 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample2.png) 121 | ```yaml 122 | type: horizontal-stack 123 | cards: 124 | - type: custom:pic-shutter-card 125 | entities: 126 | - entity: cover.roll_2 127 | name: ' ' 128 | buttons_position: not show 129 | title_position: bottom 130 | outside_window: show 131 | outside_window_pic: /local/community/pic-shutter-card/outwin1.png 132 | shutter_slide_pic: /local/community/pic-shutter-card/sc_shutter_slide.png 133 | shutter_animation: not show 134 | - type: custom:pic-shutter-card 135 | entities: 136 | - entity: cover.roll_2 137 | name: ' ' 138 | buttons_position: not show 139 | title_position: bottom 140 | outside_window: show 141 | outside_window_pic: /local/community/pic-shutter-card/outwin2.png 142 | shutter_slide_pic: /local/community/pic-shutter-card/purple.png 143 | - type: custom:pic-shutter-card 144 | entities: 145 | - entity: cover.roll_2 146 | name: ' ' 147 | buttons_position: not show 148 | title_position: bottom 149 | outside_window: show 150 | outside_window_pic: /local/community/pic-shutter-card/outwin1.png 151 | shutter_slide_pic: /local/community/pic-shutter-card/litegreen.png 152 | - type: custom:pic-shutter-card 153 | entities: 154 | - entity: cover.roll_2 155 | name: ' ' 156 | buttons_position: not show 157 | title_position: bottom 158 | outside_window: show 159 | outside_window_pic: /local/community/pic-shutter-card/outwin2.png 160 | shutter_slide_pic: /local/community/pic-shutter-card/liteblue.png 161 | shutter_animation: not show 162 | ``` 163 | 164 | **Пример кода карточки 2** 165 | 166 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample3.png) 167 | ```yaml 168 | type: horizontal-stack 169 | cards: 170 | - type: custom:pic-shutter-card 171 | entities: 172 | - entity: cover.roll_1 173 | name: Left 174 | buttons_position: left 175 | title_position: bottom 176 | outside_window: show 177 | outside_window_pic: /local/community/pic-shutter-card/outside_window2.png 178 | frame_window_pic: /local/community/pic-shutter-card/frame_window.png 179 | shutter_slide_pic: /local/community/pic-shutter-card/art1.png 180 | shutter_bottom_pic: none 181 | shutter_direction: left 182 | shutter_heigth: 135 183 | shutter_min_position: 5 184 | shutter_max_position: 95 185 | shutter_animation: show 186 | - type: custom:pic-shutter-card 187 | entities: 188 | - entity: cover.roll_1 189 | name: LeftRight 190 | buttons_position: left 191 | title_position: bottom 192 | outside_window: show 193 | outside_window_pic: /local/community/pic-shutter-card/outside_window4.png 194 | frame_window_pic: /local/community/pic-shutter-card/frame_window.png 195 | shutter_slide_pic: /local/community/pic-shutter-card/art1.png 196 | shutter_bottom_pic: none 197 | shutter_direction: leftright 198 | shutter_heigth: 135 199 | shutter_min_position: 5 200 | shutter_max_position: 95 201 | shutter_animation: show 202 | - type: custom:pic-shutter-card 203 | entities: 204 | - entity: cover.roll_1 205 | name: Right 206 | buttons_position: left 207 | title_position: bottom 208 | outside_window: show 209 | outside_window_pic: /local/community/pic-shutter-card/outside_window5.png 210 | frame_window_pic: /local/community/pic-shutter-card/frame_window.png 211 | shutter_slide_pic: /local/community/pic-shutter-card/art1.png 212 | shutter_bottom_pic: none 213 | shutter_direction: right 214 | shutter_heigth: 135 215 | shutter_min_position: 5 216 | shutter_max_position: 95 217 | shutter_animation: show 218 | ``` 219 | 220 | **Пример кода карточки 3** 221 | 222 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample4.png) 223 | ```yaml 224 | type: horizontal-stack 225 | cards: 226 | - type: custom:pic-shutter-card 227 | entities: 228 | - entity: cover.roll_1 229 | name: Left 230 | buttons_position: right 231 | title_position: bottom 232 | shutter_animation: show 233 | shutter_min_position: 5 234 | shutter_top: 4 235 | shutter_max_position: 135 236 | outside_window: show 237 | outside_window_pic: /local/community/pic-shutter-card/outside_window.png 238 | frame_window_pic: /local/community/pic-shutter-card/frame_win1.png 239 | shutter_slide_pic: /local/community/pic-shutter-card/art_city.png 240 | shutter_bottom_pic: show 241 | - type: custom:pic-shutter-card 242 | entities: 243 | - entity: cover.roll_1 244 | name: Right 245 | buttons_position: left 246 | title_position: bottom 247 | shutter_animation: show 248 | outside_window: show 249 | outside_window_pic: /local/community/pic-shutter-card/outwin1.png 250 | frame_window_pic: /local/community/pic-shutter-card/frame_win1_2.png 251 | shutter_slide_pic: /local/community/pic-shutter-card/art4.png 252 | shutter_bottom_pic: none 253 | shutter_top: -1 254 | shutter_heigth: 159 255 | shutter_direction: leftright 256 | shutter_min_position: -1 257 | shutter_max_position: 100 258 | ``` 259 | 260 | **Пример кода карточки 4** 261 | 262 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample5.png) 263 | ```yaml 264 | type: horizontal-stack 265 | cards: 266 | - type: custom:pic-shutter-card 267 | entities: 268 | - entity: cover.roll_2 269 | name: ' ' 270 | buttons_position: left 271 | title_position: bottom 272 | outside_window: show 273 | outside_window_pic: /local/community/pic-shutter-card/outside_window.png 274 | frame_window_pic: /local/community/pic-shutter-card/frame_win1.png 275 | shutter_min_position: 3 276 | shutter_top: 5 277 | shutter_max_position: 137 278 | - type: custom:pic-shutter-card 279 | entities: 280 | - entity: cover.roll_2 281 | name: ' ' 282 | buttons_position: right 283 | title_position: bottom 284 | outside_window: show 285 | outside_window_pic: /local/community/pic-shutter-card/outside_window.png 286 | frame_window_pic: /local/community/pic-shutter-card/frame_win2.png 287 | shutter_min_position: 3 288 | shutter_top: 5 289 | shutter_max_position: 142 290 | ``` 291 | 292 | **Пример кода карточки 5** 293 | 294 | ![all](https://github.com/samoswall/pic-shutter-card/blob/main/Image/sample6.gif) 295 | ```yaml 296 | type: horizontal-stack 297 | cards: 298 | - type: custom:pic-shutter-card 299 | entities: 300 | - entity: cover.roll_1 301 | name: ' ' 302 | buttons_position: left 303 | title_position: bottom 304 | outside_window: show 305 | frame_window_pic: /local/community/pic-shutter-card/pic_balcon_l.png 306 | shutter_min_position: 3 307 | shutter_top: 18 308 | shutter_left: 21 309 | shutter_max_position: 257 310 | shutter_pic_height: 300 311 | shutter_width: 74 312 | - type: custom:pic-shutter-card 313 | entities: 314 | - entity: cover.roll_2 315 | name: ' ' 316 | buttons_position: right 317 | title_position: bottom 318 | outside_window: show 319 | frame_window_pic: /local/community/pic-shutter-card/pic_balcon_r.png 320 | shutter_min_position: 3 321 | shutter_top: 18 322 | shutter_left: 3 323 | shutter_max_position: 173 324 | shutter_pic_height: 300 325 | shutter_width: 80 326 | ``` 327 | 328 | ## Благодарности 329 | 330 | Эта карточка является модернизацией карточки [hass-shutter-card](https://github.com/Deejayfool/hass-shutter-card). 331 | Спасибо автору [Deejayfool](https://github.com/Deejayfool). 332 | 333 | 334 | ## Пожертвования 335 | Вы можете поддержать этот или другие проекты. 336 | [![Donate](https://img.shields.io/badge/donate-Yandex-red.svg)](https://yoomoney.ru/fundraise/b8GYBARCVRE.230309) 337 | -------------------------------------------------------------------------------- /dist/art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/art.png -------------------------------------------------------------------------------- /dist/art1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/art1.png -------------------------------------------------------------------------------- /dist/art3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/art3.png -------------------------------------------------------------------------------- /dist/art4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/art4.png -------------------------------------------------------------------------------- /dist/art_city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/art_city.png -------------------------------------------------------------------------------- /dist/frame_win1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/frame_win1.png -------------------------------------------------------------------------------- /dist/frame_win1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/frame_win1_2.png -------------------------------------------------------------------------------- /dist/frame_win2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/frame_win2.png -------------------------------------------------------------------------------- /dist/frame_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/frame_window.png -------------------------------------------------------------------------------- /dist/liteblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/liteblue.png -------------------------------------------------------------------------------- /dist/litegreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/litegreen.png -------------------------------------------------------------------------------- /dist/outside_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outside_window.png -------------------------------------------------------------------------------- /dist/outside_window1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outside_window1.png -------------------------------------------------------------------------------- /dist/outside_window2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outside_window2.png -------------------------------------------------------------------------------- /dist/outside_window3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outside_window3.png -------------------------------------------------------------------------------- /dist/outside_window4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outside_window4.png -------------------------------------------------------------------------------- /dist/outside_window5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outside_window5.png -------------------------------------------------------------------------------- /dist/outwin1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outwin1.png -------------------------------------------------------------------------------- /dist/outwin2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outwin2.png -------------------------------------------------------------------------------- /dist/outwin3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/outwin3.png -------------------------------------------------------------------------------- /dist/pic-shutter-card.js: -------------------------------------------------------------------------------- 1 | // pic-shutter-card version 1.2.3 2 | 3 | class ShutterCard extends HTMLElement { 4 | 5 | set hass(hass) { 6 | const _this = this; 7 | const entities = this.config.entities; 8 | 9 | //Init the card 10 | if (!this.card) { 11 | const card = document.createElement('ha-card'); 12 | 13 | if (this.config.title) { 14 | card.header = this.config.title; 15 | } 16 | 17 | this.card = card; 18 | this.appendChild(card); 19 | 20 | let allShutters = document.createElement('div'); 21 | allShutters.className = 'sc-shutters'; 22 | entities.forEach(function(entity) { 23 | let entityId = entity; 24 | if (entity && entity.entity) { 25 | entityId = entity.entity; 26 | } 27 | 28 | let titlePosition = 'top'; 29 | if (entity && entity.title_position) { 30 | titlePosition = entity.title_position.toLowerCase(); 31 | } 32 | 33 | let invertPercentage = false; 34 | if (entity && entity.invert_percentage) { 35 | invertPercentage = entity.invert_percentage; 36 | } 37 | 38 | let buttonsPosition = 'left'; 39 | if (entity && entity.buttons_position) { 40 | buttonsPosition = entity.buttons_position.toLowerCase(); 41 | } 42 | 43 | let outsideWindow = 'not show'; 44 | if (entity && entity.outside_window) { 45 | outsideWindow = entity.outside_window.toLowerCase(); 46 | } 47 | 48 | let outsideWindowpic = '/hacsfiles/pic-shutter-card/outside_window.png'; 49 | if (entity && entity.outside_window_pic) { 50 | outsideWindowpic = entity.outside_window_pic.toLowerCase(); 51 | } 52 | 53 | let framewindowpic = '/hacsfiles/pic-shutter-card/frame_window.png'; 54 | if (entity && entity.frame_window_pic) { 55 | framewindowpic = entity.frame_window_pic.toLowerCase(); 56 | } 57 | 58 | let shutterslidepic = '/hacsfiles/pic-shutter-card/sc_shutter_slide.png'; 59 | if (entity && entity.shutter_slide_pic) { 60 | shutterslidepic = entity.shutter_slide_pic.toLowerCase(); 61 | } 62 | 63 | let shutterbottompic = '/hacsfiles/pic-shutter-card/sc_shutter_bottom.png'; 64 | if (entity && entity.shutter_bottom_pic) { 65 | shutterbottompic = entity.shutter_bottom_pic.toLowerCase(); 66 | } 67 | 68 | let shutterminposition = 4; 69 | if (entity && entity.shutter_min_position) { 70 | shutterminposition = parseInt(entity.shutter_min_position); 71 | } 72 | 73 | let shuttermaxposition = 127; 74 | if (entity && entity.shutter_max_position) { 75 | shuttermaxposition = parseInt(entity.shutter_max_position); 76 | } 77 | 78 | let shutterheigth = 140; 79 | if (entity && entity.shutter_heigth) { 80 | shutterheigth = parseInt(entity.shutter_heigth); 81 | } 82 | 83 | let shutterdirection = 'up'; 84 | if (entity && entity.shutter_direction) { 85 | shutterdirection = entity.shutter_direction.toLowerCase(); 86 | } 87 | 88 | let shuttertop = 17; 89 | if (entity && entity.shutter_top) { 90 | shuttertop = parseInt(entity.shutter_top); 91 | } 92 | 93 | let shutterpicheight = 155; 94 | if (entity && entity.shutter_pic_height) { 95 | shutterpicheight = parseInt(entity.shutter_pic_height); 96 | } 97 | 98 | let shutterleft = 5; 99 | if (entity && entity.shutter_left) { 100 | shutterleft = parseInt(entity.shutter_left); 101 | } 102 | 103 | let shutterwidth = 90; 104 | if (entity && entity.shutter_width) { 105 | shutterwidth = parseInt(entity.shutter_width); 106 | } 107 | 108 | let endoffset = 0; 109 | if (entity && entity.shutter_end_offset) { 110 | endoffset = parseInt(entity.shutter_end_offset); 111 | } 112 | 113 | let replace0percent = 'notuse'; 114 | if (entity && entity.replace_0_percent) { 115 | replace0percent = entity.replace_0_percent; 116 | } 117 | 118 | let replace100percent = 'notuse'; 119 | if (entity && entity.replace_100_percent) { 120 | replace100percent = entity.replace_100_percent; 121 | } 122 | 123 | _this.minPosition = shutterminposition; 124 | _this.maxPosition = shuttermaxposition; 125 | _this.shuttertop = shuttertop; 126 | _this.shutterdirection = shutterdirection; 127 | _this.setConfig(_this.config, shutterminposition, shuttermaxposition); 128 | _this.shutterpicheight = shutterpicheight; 129 | 130 | let shutter = document.createElement('div'); 131 | 132 | shutter.className = 'sc-shutter'; 133 | shutter.dataset.shutter = entityId; 134 | shutter.innerHTML = ` 135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | 147 |
148 |
149 |
150 |
151 |
152 | 157 | 162 | 167 | 172 | 177 | 182 | 187 | 192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 | `; 202 | 203 | let picture = shutter.querySelector('.sc-shutter-selector-picture'); 204 | let slide = shutter.querySelector('.sc-shutter-selector-slide'); 205 | let slide2 = shutter.querySelector('.sc-shutter-selector-slide2'); 206 | let picker = shutter.querySelector('.sc-shutter-selector-picker'); 207 | 208 | let mouseDown = function(event) { 209 | if (event.cancelable) { 210 | //Disable default drag event 211 | event.preventDefault(); 212 | } 213 | 214 | _this.isUpdating = true; 215 | 216 | document.addEventListener('mousemove', mouseMove); 217 | document.addEventListener('touchmove', mouseMove); 218 | document.addEventListener('pointermove', mouseMove); 219 | 220 | document.addEventListener('mouseup', mouseUp); 221 | document.addEventListener('touchend', mouseUp); 222 | document.addEventListener('pointerup', mouseUp); 223 | }; 224 | 225 | let mouseMove = function(event) { 226 | var newPosition = 0; 227 | switch (shutterdirection) { 228 | case 'up': 229 | newPosition = event.pageY - _this.getPictureTop(picture) - _this.shuttertop; 230 | break; 231 | case 'left': 232 | newPosition = (event.pageX - _this.getPictureLeft(picture)) / picture.offsetWidth * 100; 233 | break; 234 | case 'right': 235 | newPosition = 100 - ((event.pageX - _this.getPictureLeft(picture)) / picture.offsetWidth * 100); 236 | break; 237 | case 'leftright': 238 | newPosition = (100 - (event.pageX - _this.getPictureLeft(picture)) / picture.offsetWidth * 100) * 2; 239 | break; 240 | } 241 | _this.setPickerPosition(newPosition, picker, slide, shutterdirection, shutterheigth, slide2, shuttertop); 242 | }; 243 | 244 | let mouseUp = function(event) { 245 | _this.isUpdating = false; 246 | var newPosition = 0; 247 | switch (shutterdirection) { 248 | case 'up': 249 | newPosition = event.pageY - _this.getPictureTop(picture) - _this.shuttertop; 250 | break; 251 | case 'left': 252 | newPosition = event.pageX - _this.getPictureLeft(picture); 253 | break; 254 | case 'right': 255 | newPosition = 100 - ((event.pageX - _this.getPictureLeft(picture)) / picture.offsetWidth * 100 ); 256 | break; 257 | case 'leftright': 258 | newPosition = (100 - (event.pageX - _this.getPictureLeft(picture)) / picture.offsetWidth * 100) * 2; 259 | break; 260 | } 261 | 262 | if (newPosition < _this.minPosition) 263 | newPosition = _this.minPosition; 264 | 265 | if (newPosition > _this.maxPosition) 266 | newPosition = _this.maxPosition; 267 | 268 | let percentagePosition = 0; 269 | switch (shutterdirection) { 270 | case 'up': 271 | percentagePosition = (newPosition - _this.minPosition) * 100 / (_this.maxPosition - _this.minPosition); 272 | break; 273 | case 'left': 274 | percentagePosition = (newPosition - _this.minPosition) * 100 / (_this.maxPosition - _this.minPosition); 275 | break; 276 | case 'right': 277 | percentagePosition = 100 - ((newPosition - _this.minPosition) * 100 / (_this.maxPosition - _this.minPosition)); 278 | break; 279 | case 'leftright': 280 | percentagePosition = 100 - (((newPosition - _this.minPosition) * 100 / (_this.maxPosition - _this.minPosition))); 281 | break; 282 | } 283 | 284 | if (endoffset!=0) { percentagePosition = percentagePosition * ((100 - endoffset) / 100); } 285 | 286 | if (invertPercentage) { 287 | _this.updateShutterPosition(hass, entityId, percentagePosition); 288 | } else { 289 | _this.updateShutterPosition(hass, entityId, 100 - percentagePosition); 290 | } 291 | 292 | document.removeEventListener('mousemove', mouseMove); 293 | document.removeEventListener('touchmove', mouseMove); 294 | document.removeEventListener('pointermove', mouseMove); 295 | 296 | document.removeEventListener('mouseup', mouseUp); 297 | document.removeEventListener('touchend', mouseUp); 298 | document.removeEventListener('pointerup', mouseUp); 299 | }; 300 | 301 | //Manage slider update 302 | picker.addEventListener('mousedown', mouseDown); 303 | picker.addEventListener('touchstart', mouseDown); 304 | picker.addEventListener('pointerdown', mouseDown); 305 | 306 | //Manage click on buttons 307 | shutter.querySelectorAll('.sc-shutter-button-up, .sc-shutter-button-stop,.sc-shutter-button-down').forEach(function (button) { 308 | button.onclick = function () { 309 | const command = this.dataset.command; 310 | 311 | let service = ''; 312 | 313 | switch (command) { 314 | case 'up': 315 | service = 'open_cover'; 316 | break; 317 | 318 | case 'down': 319 | service = 'close_cover'; 320 | break; 321 | 322 | case 'stop': 323 | service = 'stop_cover'; 324 | break; 325 | } 326 | 327 | hass.callService('cover', service, { 328 | entity_id: entityId 329 | }); 330 | }; 331 | }); 332 | 333 | allShutters.appendChild(shutter); 334 | }); 335 | 336 | const style = document.createElement('style'); 337 | style.textContent = ` 338 | .sc-shutter { margin-top: 1rem; overflow: hidden; width: 100%;} 339 | .sc-shutter:first-child { margin-top: 0; } 340 | .sc-shutter-middle { display: flex; margin: 5px 5px; width: 93%; justify-content: center;} 341 | .sc-shutter-buttons { text-align: center; margin-top: 0.5rem; width: 25%; min-width: 40px;} 342 | .sc-shutter-selector-picture { position: relative; margin: auto; background-size: cover; min-height: 150px; max-height: 100%; width: auto; } 343 | .frame-window { position: relative; width: 100%; height: ` + _this.shutterpicheight + `px;} 344 | .sc-shutter-outside-window {position: absolute; left: 4%; top: 9px; height: 140px; width: 92%;} 345 | .sc-shutter-selector-slide { position: absolute; top: ` + _this.minPosition + `px; left: 5%; width: 0%; height: 0;} 346 | .sc-shutter-selector-slide2 { position: absolute; top: ` + _this.minPosition + `px; left: 5%; width: 0%; height: 0; } 347 | .sc-shutter-selector-picker { position: absolute; top: ` + _this.minPosition + `px; left: 5%; width: 0%; cursor: pointer; height: 10px; background-repeat: no-repeat; background-size: 100% 8px;} 348 | .sc-shutter-top { text-align: center; margin-top: 5px; } 349 | .sc-shutter-bottom { text-align: center; margin-bottom: 5px; } 350 | .sc-shutter-label { display: inline-block; font-size: 20px; vertical-align: middle; } 351 | .sc-shutter-position { display: inline-block; vertical-align: middle; padding: 0 6px; margin-left: 1rem; border-radius: 2px; background-color: var(--secondary-background-color); } 352 | 353 | .container_up, 354 | .container_down, 355 | .container_left, 356 | .container_right, 357 | .container_leftright_out, 358 | .container_leftright_in { 359 | display: flex; 360 | justify-content: center; 361 | align-items: center; 362 | position: absolute; 363 | pointer-events: none; 364 | } 365 | 366 | .container_up {left: 50%; top: 25%;} 367 | .container_down {left: 50%; top: 25%;} 368 | .container_left {left: 25%; top: 50%;} 369 | .container_right {left: 25%; top: 50%;} 370 | .container_leftright_out {left: 25%; top: 50%;} 371 | .container_leftright_in {left: 25%; top: 50%;} 372 | 373 | .chevron_down { 374 | position: absolute; 375 | width: 2.1rem; 376 | height: 0.48rem; 377 | opacity: 0; 378 | transform: scale(0.3); 379 | animation: move-chevron-down 3s ease-out infinite; 380 | } 381 | 382 | .chevron_down:first-child { 383 | animation: move-chevron-down 3s ease-out 1s infinite; 384 | } 385 | 386 | .chevron_down:nth-child(2) { 387 | animation: move-chevron-down 3s ease-out 2s infinite; 388 | } 389 | 390 | .chevron_up { 391 | position: absolute; 392 | width: 2.1rem; 393 | height: 0.48rem; 394 | opacity: 0; 395 | transform: scale(0.3); 396 | animation: move-chevron-up 3s ease-out infinite; 397 | } 398 | 399 | .chevron_up:first-child { 400 | animation: move-chevron-up 3s ease-out 1s infinite; 401 | } 402 | 403 | .chevron_up:nth-child(2) { 404 | animation: move-chevron-up 3s ease-out 2s infinite; 405 | } 406 | 407 | .chevron_left { 408 | position: absolute; 409 | width: 0.9rem; 410 | height: 2.1rem; 411 | opacity: 0; 412 | transform: scale(0.3); 413 | animation: move-chevron-left 3s ease-out infinite; 414 | } 415 | 416 | .chevron_left:first-child { 417 | animation: move-chevron-left 3s ease-out 1s infinite; 418 | } 419 | 420 | .chevron_left:nth-child(2) { 421 | animation: move-chevron-left 3s ease-out 2s infinite; 422 | } 423 | 424 | .chevron_right { 425 | position: absolute; 426 | width: 0.9rem; 427 | height: 2.1rem; 428 | opacity: 0; 429 | transform: scale(0.3); 430 | animation: move-chevron-right 3s ease-out infinite; 431 | } 432 | 433 | .chevron_right:first-child { 434 | animation: move-chevron-right 3s ease-out 1s infinite; 435 | } 436 | 437 | .chevron_right:nth-child(2) { 438 | animation: move-chevron-right 3s ease-out 2s infinite; 439 | } 440 | 441 | .chevron_leftright_out { 442 | position: absolute; 443 | width: 0.9rem; 444 | height: 2.1rem; 445 | opacity: 0; 446 | transform: scale(0.3); 447 | animation: move-chevron-leftright_out 3s ease-out infinite; 448 | } 449 | 450 | .chevron_leftright_out:first-child { 451 | animation: move-chevron-leftright_out 3s ease-out 1s infinite; 452 | } 453 | 454 | .chevron_leftright_out:nth-child(2) { 455 | animation: move-chevron-leftright_out 3s ease-out 2s infinite; 456 | } 457 | 458 | .chevron_rightleft_out { 459 | position: absolute; 460 | width: 0.9rem; 461 | height: 2.1rem; 462 | opacity: 0; 463 | transform: scale(0.3); 464 | animation: move-chevron-rightleft_out 3s ease-out infinite; 465 | } 466 | 467 | .chevron_rightleft_out:first-child { 468 | animation: move-chevron-rightleft_out 3s ease-out 1s infinite; 469 | } 470 | 471 | .chevron_rightleft_out:nth-child(2) { 472 | animation: move-chevron-rightleft_out 3s ease-out 2s infinite; 473 | } 474 | 475 | .chevron_leftright_in { 476 | position: absolute; 477 | width: 0.9rem; 478 | height: 2.1rem; 479 | opacity: 0; 480 | transform: scale(0.3); 481 | animation: move-chevron-leftright_in 3s ease-out infinite; 482 | } 483 | 484 | .chevron_leftright_in:first-child { 485 | animation: move-chevron-leftright_in 3s ease-out 1s infinite; 486 | } 487 | 488 | .chevron_leftright_in:nth-child(2) { 489 | animation: move-chevron-leftright_in 3s ease-out 2s infinite; 490 | } 491 | 492 | .chevron_rightleft_in { 493 | position: absolute; 494 | width: 0.9rem; 495 | height: 2.1rem; 496 | opacity: 0; 497 | transform: scale(0.3); 498 | animation: move-chevron-rightleft_in 3s ease-out infinite; 499 | } 500 | 501 | .chevron_rightleft_in:first-child { 502 | animation: move-chevron-rightleft_in 3s ease-out 1s infinite; 503 | } 504 | 505 | .chevron_rightleft_in:nth-child(2) { 506 | animation: move-chevron-rightleft_in 3s ease-out 2s infinite; 507 | } 508 | 509 | .chevron_up:before, 510 | .chevron_up:after, 511 | .chevron_down:before, 512 | .chevron_down:after, 513 | .chevron_left:before, 514 | .chevron_left:after, 515 | .chevron_right:before, 516 | .chevron_right:after, 517 | .chevron_leftright_out:before, 518 | .chevron_leftright_out:after, 519 | .chevron_rightleft_out:before, 520 | .chevron_rightleft_out:after, 521 | .chevron_leftright_in:before, 522 | .chevron_leftright_in:after, 523 | .chevron_rightleft_in:before, 524 | .chevron_rightleft_in:after { 525 | content: ''; 526 | position: absolute; 527 | top: 0; 528 | height: 100%; 529 | width: 50%; 530 | background: var(--paper-item-icon-color, #44739e); 531 | } 532 | 533 | .chevron_down:before { 534 | left: 0; 535 | transform: skewY(30deg); 536 | } 537 | 538 | .chevron_down:after { 539 | right: 0; 540 | width: 50%; 541 | transform: skewY(-30deg); 542 | } 543 | 544 | .chevron_up:before { 545 | left: 0; 546 | transform: skewY(-30deg); 547 | } 548 | 549 | .chevron_up:after { 550 | right: 0; 551 | width: 50%; 552 | transform: skewY(30deg); 553 | } 554 | 555 | .chevron_left:before { 556 | top: 50%; 557 | height: 50%; 558 | transform: skewX(30deg); 559 | } 560 | 561 | .chevron_left:after { 562 | bottom: 0; 563 | height: 50%; 564 | transform: skewX(-30deg); 565 | } 566 | 567 | .chevron_right:before { 568 | top: 50%; 569 | height: 50%; 570 | transform: skewX(-30deg); 571 | } 572 | 573 | .chevron_right:after { 574 | bottom: 0; 575 | height: 50%; 576 | transform: skewX(30deg); 577 | } 578 | 579 | .chevron_leftright_out:before { 580 | top: 50%; 581 | height: 50%; 582 | transform: skewX(-30deg); 583 | } 584 | 585 | .chevron_leftright_out:after { 586 | bottom: 0; 587 | height: 50%; 588 | transform: skewX(30deg); 589 | } 590 | 591 | .chevron_rightleft_out:before { 592 | top: 50%; 593 | height: 50%; 594 | transform: skewX(30deg); 595 | } 596 | 597 | .chevron_rightleft_out:after { 598 | bottom: 0; 599 | height: 50%; 600 | transform: skewX(-30deg); 601 | } 602 | 603 | .chevron_leftright_in:before { 604 | top: 50%; 605 | height: 50%; 606 | transform: skewX(30deg); 607 | } 608 | 609 | .chevron_leftright_in:after { 610 | bottom: 0; 611 | height: 50%; 612 | transform: skewX(-30deg); 613 | } 614 | 615 | .chevron_rightleft_in:before { 616 | top: 50%; 617 | height: 50%; 618 | transform: skewX(-30deg); 619 | } 620 | 621 | .chevron_rightleft_in:after { 622 | bottom: 0; 623 | height: 50%; 624 | transform: skewX(30deg); 625 | } 626 | 627 | @keyframes move-chevron-down { 628 | 25% { 629 | opacity: 1; 630 | } 631 | 33.3% { 632 | opacity: 1; 633 | transform: translateY(2.28rem); 634 | } 635 | 66.6% { 636 | opacity: 1; 637 | transform: translateY(3.12rem); 638 | } 639 | 100% { 640 | opacity: 0; 641 | transform: translateY(4.8rem) scale(0.5); 642 | } 643 | } 644 | 645 | @keyframes move-chevron-up { 646 | 100% { 647 | opacity: 0; 648 | } 649 | 66.6% { 650 | opacity: 1; 651 | transform: translateY(2.28rem); 652 | } 653 | 33.3% { 654 | opacity: 1; 655 | transform: translateY(3.12rem); 656 | } 657 | 25% { 658 | opacity: 1; 659 | } 660 | 1% { 661 | opacity: 0; 662 | transform: translateY(4.8rem) scale(0.5); 663 | } 664 | } 665 | 666 | @keyframes move-chevron-left { 667 | 100% { 668 | opacity: 0; 669 | } 670 | 66.6% { 671 | opacity: 1; 672 | transform: translateX(2.28rem); 673 | } 674 | 33.3% { 675 | opacity: 1; 676 | transform: translateX(3.12rem); 677 | } 678 | 25% { 679 | opacity: 1; 680 | } 681 | 1% { 682 | opacity: 0; 683 | transform: translateX(4.8rem) scale(0.5); 684 | } 685 | } 686 | 687 | @keyframes move-chevron-right { 688 | 25% { 689 | opacity: 1; 690 | } 691 | 33.3% { 692 | opacity: 1; 693 | transform: translateX(2.28rem); 694 | } 695 | 66.6% { 696 | opacity: 1; 697 | transform: translateX(3.12rem); 698 | } 699 | 100% { 700 | opacity: 0; 701 | transform: translateX(4.8rem) scale(0.5); 702 | } 703 | } 704 | 705 | @keyframes move-chevron-leftright_out { 706 | 33.3% { 707 | opacity: 0; 708 | transform: translateX(50px) scale(0.5); 709 | } 710 | 50% { 711 | opacity: 1; 712 | transform: translateX(50px); 713 | } 714 | 66.6% { 715 | opacity: 1; 716 | transform: translateX(65px); 717 | } 718 | 100% { 719 | opacity: 0; 720 | transform: translateX(80px) scale(0.5); 721 | } 722 | } 723 | 724 | @keyframes move-chevron-rightleft_out { 725 | 33.3% { 726 | opacity: 0; 727 | transform: translateX(30px) scale(0.5); 728 | } 729 | 50% { 730 | opacity: 1; 731 | transform: translateX(30px); 732 | } 733 | 66.6% { 734 | opacity: 1; 735 | transform: translateX(15px); 736 | } 737 | 100% { 738 | opacity: 0; 739 | transform: scale(0.5); 740 | } 741 | } 742 | 743 | @keyframes move-chevron-leftright_in { 744 | 33.3% { 745 | opacity: 0; 746 | transform: translateX(70px) scale(0.5); 747 | } 748 | 50% { 749 | opacity: 1; 750 | transform: translateX(70px); 751 | } 752 | 66.6% { 753 | opacity: 1; 754 | transform: translateX(55px); 755 | } 756 | 100% { 757 | opacity: 0; 758 | transform: translateX(40px) scale(0.5); 759 | } 760 | } 761 | 762 | @keyframes move-chevron-rightleft_in { 763 | 764 | 33.3% { 765 | opacity: 0; 766 | transform: translateX(0px) scale(0.5); 767 | } 768 | 50% { 769 | opacity: 1; 770 | transform: translateX(0px); 771 | } 772 | 66.6% { 773 | opacity: 1; 774 | transform: translateX(15px); 775 | } 776 | 100% { 777 | opacity: 0; 778 | transform: translateX(30px) scale(0.5); 779 | } 780 | } 781 | `; 782 | 783 | this.card.appendChild(allShutters); 784 | this.appendChild(style); 785 | } 786 | 787 | //Update the shutters UI 788 | entities.forEach(function(entity) { 789 | let entityId = entity; 790 | if (entity && entity.entity) { 791 | entityId = entity.entity; 792 | } 793 | 794 | let invertPercentage = false; 795 | if (entity && entity.invert_percentage) { 796 | invertPercentage = entity.invert_percentage; 797 | } 798 | let shutteranimation = 'show'; 799 | if (entity && entity.shutter_animation) { 800 | shutteranimation = entity.shutter_animation; 801 | } 802 | let shutterheigth = 140; 803 | if (entity && entity.shutter_heigth) { 804 | shutterheigth = parseInt(entity.shutter_heigth); 805 | } 806 | let shutterdirection = 'up'; 807 | if (entity && entity.shutter_direction) { 808 | shutterdirection = entity.shutter_direction.toLowerCase(); 809 | } 810 | let shuttertop = 17; 811 | if (entity && entity.shutter_top) { 812 | shuttertop = parseInt(entity.shutter_top); 813 | } 814 | 815 | let shutterminposition = 4; 816 | if (entity && entity.shutter_min_position) { 817 | shutterminposition = parseInt(entity.shutter_min_position); 818 | } 819 | 820 | let shuttermaxposition = 127; 821 | if (entity && entity.shutter_max_position) { 822 | shuttermaxposition = parseInt(entity.shutter_max_position); 823 | } 824 | 825 | let shutterwidth = 90; 826 | if (entity && entity.shutter_width) { 827 | shutterwidth = parseInt(entity.shutter_width); 828 | } 829 | 830 | let endoffset = 0; 831 | if (entity && entity.shutter_end_offset) { 832 | endoffset = parseInt(entity.shutter_end_offset); 833 | } 834 | 835 | let replace0percent = 'notuse'; 836 | if (entity && entity.replace_0_percent) { 837 | replace0percent = entity.replace_0_percent; 838 | } 839 | 840 | let replace100percent = 'notuse'; 841 | if (entity && entity.replace_100_percent) { 842 | replace100percent = entity.replace_100_percent; 843 | } 844 | 845 | const shutter = _this.card.querySelector('div[data-shutter="' + entityId +'"]'); 846 | const slide = shutter.querySelector('.sc-shutter-selector-slide'); 847 | const picker = shutter.querySelector('.sc-shutter-selector-picker'); 848 | const slide2 = shutter.querySelector('.sc-shutter-selector-slide2'); 849 | const buttonup = shutter.querySelector('.sc-shutter-button-up'); 850 | const buttondown = shutter.querySelector('.sc-shutter-button-down'); 851 | 852 | const state = hass.states[entityId]; 853 | const friendlyName = (entity && entity.name) ? entity.name : state ? state.attributes.friendly_name : 'unknown'; 854 | let currentPosition = state ? state.attributes.current_position : '100'; 855 | const movementState = state? state.state : 'unknown'; 856 | shutter.querySelectorAll('.sc-shutter-label').forEach(function(shutterLabel) { 857 | shutterLabel.innerHTML = friendlyName; 858 | }) 859 | 860 | if (endoffset!=0) { 861 | currentPosition = Math.floor(( currentPosition * 100) / (100 - endoffset)); 862 | if (currentPosition>100) {currentPosition = 100} 863 | } 864 | 865 | if (!_this.isUpdating) { 866 | shutter.querySelectorAll('.sc-shutter-position').forEach(function (shutterPosition) { 867 | if ((currentPosition == 100 || currentPosition == 0) && (replace0percent != 'notuse' || replace100percent != 'notuse')) { 868 | if (currentPosition == 100){ 869 | shutterPosition.innerHTML = invertPercentage?(replace0percent):(replace100percent); 870 | } else { 871 | shutterPosition.innerHTML = invertPercentage?(replace100percent):(replace0percent); 872 | } 873 | } else { 874 | shutterPosition.innerHTML = invertPercentage?((100 - currentPosition) + '%'):(currentPosition + '%'); 875 | } 876 | if (currentPosition == 0 || currentPosition == 100) { 877 | if (currentPosition == 100) { 878 | buttonup.style.color = invertPercentage?('var(--primary-text-color)'):('var(--disabled-text-color)'); 879 | buttonup.style.pointerEvents = invertPercentage?'auto':'none'; 880 | buttondown.style.color = invertPercentage?('var(--disabled-text-color)'):('var(--primary-text-color)'); 881 | buttondown.style.pointerEvents = invertPercentage?'none':'auto'; 882 | } 883 | if (currentPosition == 0) { 884 | buttonup.style.color = invertPercentage?('var(--disabled-text-color)'):('var(--primary-text-color)'); 885 | buttonup.style.pointerEvents = invertPercentage?'none':'auto'; 886 | buttondown.style.color = invertPercentage?('var(--primary-text-color)'):('var(--disabled-text-color)'); 887 | buttondown.style.pointerEvents = invertPercentage?'auto':'none'; 888 | } 889 | } else { 890 | buttonup.style.color = 'var(--primary-text-color)'; 891 | buttonup.style.pointerEvents = 'auto'; 892 | buttondown.style.color = 'var(--primary-text-color)'; 893 | buttondown.style.pointerEvents = 'auto'; 894 | } 895 | }) 896 | 897 | if (invertPercentage) { 898 | _this.setPickerPositionPercentage(currentPosition, picker, slide, shutterdirection, shutterheigth, slide2, shuttertop, shutterwidth); 899 | } else { 900 | _this.setPickerPositionPercentage(100 - currentPosition, picker, slide, shutterdirection, shutterheigth, slide2, shuttertop, shutterwidth); 901 | } 902 | if (shutteranimation == 'show') { _this.setMovement(movementState, shutter, shutterdirection, invertPercentage); } 903 | } 904 | }); 905 | } 906 | 907 | setMovement(movement, shutter,shutterdirection, invertPercentage) { 908 | if (movement == "opening" || movement == "closing") { 909 | let opening = invertPercentage?(movement == "closing"):(movement == "opening") 910 | switch (shutterdirection) { 911 | case 'up': 912 | shutter.querySelectorAll(".container_up").forEach( 913 | (overlay) => overlay.style.display = opening?"flex":"none" 914 | ) 915 | shutter.querySelectorAll(".container_down").forEach( 916 | (overlay) => overlay.style.display = opening?"none":"flex" 917 | ) 918 | break; 919 | case 'left': 920 | shutter.querySelectorAll(".container_left").forEach( 921 | (overlay) => overlay.style.display = opening?"flex":"none" 922 | ) 923 | shutter.querySelectorAll(".container_right").forEach( 924 | (overlay) => overlay.style.display = opening?"none":"flex" 925 | ) 926 | break; 927 | case 'right': 928 | shutter.querySelectorAll(".container_right").forEach( 929 | (overlay) => overlay.style.display = opening?"flex":"none" 930 | ) 931 | shutter.querySelectorAll(".container_left").forEach( 932 | (overlay) => overlay.style.display = opening?"none":"flex" 933 | ) 934 | break; 935 | case 'leftright': 936 | shutter.querySelectorAll(".container_leftright_out").forEach( 937 | (overlay) => overlay.style.display = opening?"flex":"none" 938 | ) 939 | shutter.querySelectorAll(".container_leftright_in").forEach( 940 | (overlay) => overlay.style.display = opening?"none":"flex" 941 | ) 942 | break; 943 | } 944 | } 945 | else { 946 | shutter.querySelectorAll(".container_up").forEach( 947 | (overlay) => overlay.style.display = "none" 948 | ) 949 | shutter.querySelectorAll(".container_down").forEach( 950 | (overlay) => overlay.style.display = "none" 951 | ) 952 | shutter.querySelectorAll(".container_left").forEach( 953 | (overlay) => overlay.style.display = "none" 954 | ) 955 | shutter.querySelectorAll(".container_right").forEach( 956 | (overlay) => overlay.style.display = "none" 957 | ) 958 | shutter.querySelectorAll(".container_leftright_in").forEach( 959 | (overlay) => overlay.style.display = "none" 960 | ) 961 | shutter.querySelectorAll(".container_leftright_out").forEach( 962 | (overlay) => overlay.style.display = "none" 963 | ) 964 | } 965 | } 966 | 967 | getPictureTop(picture) { 968 | let pictureBox = picture.getBoundingClientRect(); 969 | let body = document.body; 970 | let docEl = document.documentElement; 971 | let scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; 972 | let clientTop = docEl.clientTop || body.clientTop || 0; 973 | let pictureTop = pictureBox.top + scrollTop - clientTop; 974 | return pictureTop; 975 | } 976 | 977 | getPictureLeft(picture) { 978 | let pictureBox = picture.getBoundingClientRect(); 979 | let body = document.body; 980 | let docEl = document.documentElement; 981 | let scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; 982 | let clientLeft = docEl.clientLeft || body.clientLeft || 0; 983 | let pictureLeft = pictureBox.left + scrollLeft - clientLeft; 984 | return pictureLeft; 985 | } 986 | 987 | setPickerPositionPercentage(position, picker, slide, shutterdirection, shutterheigth, slide2, shuttertop, shutterwidth) { 988 | let realPosition = (this.maxPosition - this.minPosition) * position / 100 + this.minPosition; 989 | 990 | this.setPickerPosition(realPosition, picker, slide, shutterdirection, shutterheigth, slide2, shuttertop, shutterwidth); 991 | } 992 | 993 | setPickerPosition(position, picker, slide, shutterdirection, shutterheigth, slide2, shuttertop, shutterwidth) { 994 | if (position < this.minPosition) 995 | position = this.minPosition; 996 | 997 | if (position > this.maxPosition) 998 | position = this.maxPosition; 999 | 1000 | switch (shutterdirection) { 1001 | case 'up': 1002 | picker.style.top = position + this.minPosition + shuttertop - 8 + 'px'; 1003 | slide.style.height = position + this.minPosition + 'px'; 1004 | slide.style.width = shutterwidth + '%'; 1005 | picker.style.width = slide.style.width; 1006 | picker.style.height = '10px'; 1007 | break; 1008 | case 'left': 1009 | slide.style.height = shutterheigth + 'px'; 1010 | slide.style.backgroundSize = 'auto ' + shutterheigth + 'px'; 1011 | slide.style.width = (position / this.maxPosition * 100 * (this.maxPosition / 100) - this.minPosition) + '%'; 1012 | slide.style.backgroundPosition = 'right bottom'; 1013 | slide.style.left = this.minPosition + '%'; 1014 | picker.style.width = '10px'; 1015 | picker.style.height = slide.style.height; 1016 | picker.style.left = position - 6 + '%'; 1017 | break; 1018 | case 'right': 1019 | slide.style.height = shutterheigth + 'px'; 1020 | slide.style.backgroundSize = 'auto ' + shutterheigth + 'px'; 1021 | slide.style.width = (position / this.maxPosition * 100 * (this.maxPosition / 100) - this.minPosition) + '%'; 1022 | slide.style.left = this.maxPosition - position + this.minPosition + '%'; 1023 | slide.style.backgroundPosition = 'left bottom'; 1024 | picker.style.width = '10px'; 1025 | picker.style.height = slide.style.height; 1026 | picker.style.left = this.maxPosition - position + this.minPosition + '%'; 1027 | break; 1028 | case 'leftright': 1029 | slide.style.height = shutterheigth + 'px'; 1030 | slide.style.backgroundSize = 'auto ' + shutterheigth + 'px'; 1031 | slide.style.backgroundPosition = 'right bottom'; 1032 | slide.style.width = (position / this.maxPosition * 100 * (this.maxPosition / 100) - this.minPosition) / 2 + '%'; 1033 | slide.style.left = this.minPosition + '%'; 1034 | 1035 | slide2.style.height = shutterheigth + 'px'; 1036 | slide2.style.backgroundSize = 'auto ' + shutterheigth + 'px'; 1037 | slide2.style.backgroundPosition = 'left bottom'; 1038 | slide2.style.width = (position / this.maxPosition * 100 * (this.maxPosition / 100) - this.minPosition) / 2 + '%'; 1039 | slide2.style.left = (this.maxPosition - position + this.minPosition) + (position / this.maxPosition * 100 * (this.maxPosition / 100) - this.minPosition) / 2 + '%'; 1040 | picker.style.width = '10px'; 1041 | picker.style.height = slide.style.height; 1042 | picker.style.left = this.maxPosition - (position / 2) + '%'; 1043 | break; 1044 | } 1045 | } 1046 | 1047 | updateShutterPosition(hass, entityId, position) { 1048 | let shutterPosition = Math.round(position); 1049 | 1050 | hass.callService('cover', 'set_cover_position', { 1051 | entity_id: entityId, 1052 | position: shutterPosition 1053 | }); 1054 | } 1055 | 1056 | setConfig(config, mmin, mmax) { 1057 | if (!config.entities) { 1058 | throw new Error('You need to define entities'); 1059 | } 1060 | this.config = config; 1061 | this.maxPosition = mmax; 1062 | this.minPosition = mmin; 1063 | this.isUpdating = false; 1064 | } 1065 | 1066 | // The height of your card. Home Assistant uses this to automatically 1067 | // distribute all cards over the available columns. 1068 | getCardSize() { 1069 | return this.config.entities.length + 1; 1070 | } 1071 | } 1072 | 1073 | customElements.define("pic-shutter-card", ShutterCard); 1074 | -------------------------------------------------------------------------------- /dist/pic_balcon_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/pic_balcon_l.png -------------------------------------------------------------------------------- /dist/pic_balcon_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/pic_balcon_r.png -------------------------------------------------------------------------------- /dist/purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/purple.png -------------------------------------------------------------------------------- /dist/sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sample.gif -------------------------------------------------------------------------------- /dist/sample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sample1.png -------------------------------------------------------------------------------- /dist/sample2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sample2.png -------------------------------------------------------------------------------- /dist/sample3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sample3.png -------------------------------------------------------------------------------- /dist/sample4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sample4.png -------------------------------------------------------------------------------- /dist/sample5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sample5.png -------------------------------------------------------------------------------- /dist/sc_shutter_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sc_shutter_bottom.png -------------------------------------------------------------------------------- /dist/sc_shutter_slide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samoswall/pic-shutter-card/43d8cfe954bcc0cabf898c970732a26420916d60/dist/sc_shutter_slide.png -------------------------------------------------------------------------------- /hacs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pic-Shutter-Card", 3 | "filename": "pic-shutter-card.js", 4 | "render_readme": true, 5 | "homeassistant": "2021.11.0" 6 | } 7 | --------------------------------------------------------------------------------