1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace luya\lazyload; |
4
|
|
|
|
5
|
|
|
use luya\base\Widget; |
6
|
|
|
use yii\base\InvalidConfigException; |
7
|
|
|
use yii\helpers\Html; |
8
|
|
|
use luya\web\View; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Image Lazy Loader. |
12
|
|
|
* |
13
|
|
|
* ```php |
14
|
|
|
* <?= LazyLoad::widget(['src' => 'http://www.zephir.ch/img/zephir-logo.png']); ?> |
15
|
|
|
* ``` |
16
|
|
|
* |
17
|
|
|
* In order to read more visit the [[concept-lazyload.md]] guide section. |
18
|
|
|
* |
19
|
|
|
* @author Basil Suter <[email protected]> |
20
|
|
|
* @author Marc Stampfli <[email protected]> |
21
|
|
|
* @author Alex Schmid <[email protected]> |
22
|
|
|
* @since 1.0.0 |
23
|
|
|
*/ |
24
|
|
|
class LazyLoad extends Widget |
25
|
|
|
{ |
26
|
|
|
const JS_ASSET_KEY = 'lazyload.js.register'; |
27
|
|
|
|
28
|
|
|
const CSS_ASSET_KEY = 'lazyload.css.register'; |
29
|
|
|
const CSS_ASSET_KEY_PLACEHOLDER = 'lazyload.placeholder.css.register'; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var string The path to the image you want to lazy load. |
33
|
|
|
*/ |
34
|
|
|
public $src; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var string Path for the placeholder image that will be base64 encoded. |
38
|
|
|
* @since 1.0.14 |
39
|
|
|
*/ |
40
|
|
|
public $placeholderSrc; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var boolean Inline the placeholder source as base64 encoded string |
44
|
|
|
* @since 1.0.14 |
45
|
|
|
*/ |
46
|
|
|
public $placeholderAsBase64 = false; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var integer The width of the image, this information should be provided in order to display a placeholder. |
50
|
|
|
*/ |
51
|
|
|
public $width; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var integer The height of the image, this information should be provided in order to display a placeholder. |
55
|
|
|
*/ |
56
|
|
|
public $height; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var boolean Define whether a full image tag should be return or only the attributes. This can be applied when using the lazy loader in background images. |
60
|
|
|
*/ |
61
|
|
|
public $attributesOnly = false; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var string Additional classes for the lazy load image. |
65
|
|
|
*/ |
66
|
|
|
public $extraClass; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @var array Options array for the html tag. This array can be used to pass e.g. a `title` or `alt` tag. |
70
|
|
|
* @since 1.6.0 |
71
|
|
|
*/ |
72
|
|
|
public $options = []; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @var array Legacy support for older Browsers (Adds the IntersectionOberserver Polyfill, default: true) |
76
|
|
|
* @since 1.6.0 |
77
|
|
|
*/ |
78
|
|
|
public $legacySupport = true; |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* @var array Optionally disable the automatic init of the lazyload function so you can override the JS options |
82
|
|
|
* @since 1.6.0 |
83
|
|
|
*/ |
84
|
|
|
public $initJs = true; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @var string The default classes which will be registered. |
88
|
|
|
* @since 1.6.1 |
89
|
|
|
*/ |
90
|
|
|
public $defaultCss = '.lazyimage-wrapper { |
91
|
|
|
display: block; |
92
|
|
|
width: 100%; |
93
|
|
|
position: relative; |
94
|
|
|
overflow: hidden; |
95
|
|
|
} |
96
|
|
|
.lazyimage { |
97
|
|
|
position: absolute; |
98
|
|
|
top: 50%; |
99
|
|
|
left: 50%; |
100
|
|
|
bottom: 0; |
101
|
|
|
right: 0; |
102
|
|
|
opacity: 0; |
103
|
|
|
height: 100%; |
104
|
|
|
width: 100%; |
105
|
|
|
-webkit-transition: .5s ease-in-out opacity; |
106
|
|
|
transition: .5s ease-in-out opacity; |
107
|
|
|
-webkit-transform: translate(-50%,-50%); |
108
|
|
|
transform: translate(-50%,-50%); |
109
|
|
|
-o-object-fit: cover; |
110
|
|
|
object-fit: cover; |
111
|
|
|
-o-object-position: center center; |
112
|
|
|
object-position: center center; |
113
|
|
|
z-index: 20; |
114
|
|
|
} |
115
|
|
|
.lazyimage.loaded { |
116
|
|
|
opacity: 1; |
117
|
|
|
} |
118
|
|
|
.lazyimage-placeholder { |
119
|
|
|
display: block; |
120
|
|
|
width: 100%; |
121
|
|
|
height: auto; |
122
|
|
|
background-color: #f0f0f0; |
123
|
|
|
} |
124
|
|
|
.nojs .lazyimage, |
125
|
|
|
.nojs .lazyimage-placeholder, |
126
|
|
|
.no-js .lazyimage, |
127
|
|
|
.no-js .lazyimage-placeholder { |
128
|
|
|
display: none; |
129
|
|
|
}'; |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* @inheritdoc |
133
|
|
|
*/ |
134
|
|
|
public function init() |
135
|
|
|
{ |
136
|
|
|
parent::init(); |
137
|
|
|
|
138
|
|
|
if ($this->src === null) { |
139
|
|
|
throw new InvalidConfigException("The parameter src is required by the lazyload widget."); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
// register the asset file |
143
|
|
|
if ($this->legacySupport) { |
|
|
|
|
144
|
|
|
IntersectionObserverPolyfillAsset::register($this->view); |
145
|
|
|
} |
146
|
|
|
LazyLoadAsset::register($this->view); |
147
|
|
|
|
148
|
|
|
if ($this->initJs) { |
|
|
|
|
149
|
|
|
// register js and css code with keys in order to ensure the registration is done only once |
150
|
|
|
$this->view->registerJs("$.lazyLoad();", View::POS_READY, self::JS_ASSET_KEY); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
$this->view->registerCss($this->defaultCss, [], self::CSS_ASSET_KEY); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Returns the aspect ration based on height or width. |
158
|
|
|
* |
159
|
|
|
* If no width or height is provided, the default value 56.25 will be returned. |
160
|
|
|
* |
161
|
|
|
* @return float A dot seperated ratio value |
162
|
|
|
* @since 1.6.1 |
163
|
|
|
*/ |
164
|
|
|
protected function generateAspectRation() |
165
|
|
|
{ |
166
|
|
|
return ($this->height && $this->width) ? str_replace(',', '.', ($this->height / $this->width) * 100) : 56.25; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @inheritdoc |
171
|
|
|
*/ |
172
|
|
|
public function run() |
173
|
|
|
{ |
174
|
|
|
if ($this->placeholderSrc && $this->placeholderAsBase64) { |
175
|
|
|
$this->placeholderSrc = 'data:image/jpg;base64,' . base64_encode(file_get_contents($this->placeholderSrc)); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
if ($this->attributesOnly && !$this->placeholderSrc) { |
179
|
|
|
return "class=\"js-lazyimage {$this->extraClass}\" data-src=\"$this->src\" data-width=\"$this->width\" data-height=\"$this->height\" data-as-background=\"1\""; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
$tag = '<div class="lazyimage-wrapper ' . $this->extraClass . '">'; |
183
|
|
|
$tag .= Html::tag('img', '', array_merge($this->options, ['class' => 'js-lazyimage lazyimage', 'data-src' => $this->src, 'data-width' => $this->width, 'data-height' => $this->height])); |
184
|
|
|
if ($this->placeholderSrc) { |
185
|
|
|
$tag .= Html::tag('img', '', ['class' => 'lazyimage-placeholder', 'src' => $this->placeholderSrc]); |
186
|
|
|
} else { |
187
|
|
|
$tag .= '<div class="lazyimage-placeholder"><div style="display: block; height: 0px; padding-bottom: ' . $this->generateAspectRation() . '%;"></div><div class="loader"></div></div>'; |
188
|
|
|
} |
189
|
|
|
$tag .= '<noscript><img class="lazyimage loaded ' . $this->extraClass . '" src="'.$this->src.'" /></noscript>'; |
190
|
|
|
$tag .= '</div>'; |
191
|
|
|
|
192
|
|
|
return $tag; |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.