前台最大的作用就是展示图片,在用户点击后,可以将图片弹出放大展示出来。
JQuery有两个插件可以帮我们达到我们的目标
Magnific-Popup(http://dimsemenov.com/plugins/magnific-popup/): 用来制作弹出窗口。
Bricks(https://github.com/floo51/jquery-bricks): 多个图片存在时,自动帮我们调整图片大小,使其能够排在同一行。
Magnific-Popup可以通过Composer进行安装,在Yii目录下的composer.json的require节点下添加内容
"require": {
...
"dimsemenov/magnific-popup": "*",
...
},
然后在yii的目录下启动命令行工具,运行composer update。
安装后的文件放置在vendor文件夹下,要应用到前台页面中,需要做成AssetBundle暴露出来。用AssetBundle的另外的好处是,可以帮我们处理依赖关系,并且可以只在需要的地方使用这些资源而不是每个页面都把这些东西包裹进来增加负担。
在frontend/assets下新建MangificPopupAsset.php,内容如下
namespace frontend\assets;
use yii\web\AssetBundle;
class MagnificPopupAsset extends AssetBundle
{
public $sourcePath = '@vendor/dimsemenov/magnific-popup/dist';
public $css = [
'magnific-popup.css',
];
public $js = [
'jquery.magnific-popup.js',
];
public $depends = [
'yii\web\JqueryAsset',
];
}
前期准备工作就绪,可以开始编写widget。
新建frontend/widgets/ImagePopup.php(文件夹没有则新建)
父类为yii\base\Widget,主要需要复写init和run方法。init用于初始化参数,run用来渲染成html代码。
具体代码如下
namespace frontend\widgets;
use yii\base\Widget;
use yii\base\InvalidConfigException;
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\web\View;
use frontend\assets\MagnificPopupAsset;
class ImagePopup extends Widget {
public $options;
public $clientOptions = [];
public function init() {
if (!isset($this->options['src'])) {
throw new InvalidConfigException("Image src must provided");
}
if (!isset($this->options['dest'])) {
throw new InvalidConfigException("Popup destination must provided");
}
if (!isset($this->options['type'])) {
if(isset($this->clientOptions['type'])) {
$this->options['type'] = $this->clientOptions['type'];
} else {
$this->options['type'] = 'ajax';
}
}
if (!isset($this->options['id'])) {
$this->options['id'] = $this->getId();
}
if (!isset($this->options['wrapDiv'])) {
$this->options['wrapDiv'] = true;
}
if (!isset($this->options['class'])) {
$this->options['class'] = '';
}
$_options = [
"items" => [ "src" => $this->options['dest'], ],
"type" => $this->options['type'],
];
$this->clientOptions = ArrayHelper::merge($_options, $this->clientOptions);
parent::init();
}
public function run() {
$this->registerClientScript();
if ($this->options['wrapDiv']) {
$result = "<div id='" . $this->options['id'] . "' ";
$result .= "class='" . $this->options['class'] . "'";
$result .= ">";
$result .= Html::img($this->options['src']);
$result .= "</div>";
return $result;
} else {
return Html::img($this->options['src'], [
'id' => $this->options['id'],
'class' => $this->options['class'],
]);
}
}
protected function registerClientScript() {
MagnificPopupAsset::register($this->view);
$option = Json::encode($this->clientOptions);
$script = "$('#" . $this->options['id'] . "').magnificPopup(" . $option . ")";
$this->view->registerJs($script, View::POS_READY);
}
}
然后就可以以如下方式调用该控件
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/1.jpg",
"dest" => $url,
]
]);
其中src参数是展示的缩略图,dest是点击后弹出的东西,可以是一个url,以ajax调用,也可以是一个图片地址,直接展示图片。
弹出窗口的html源码略。
然后引用另一个JQuery插件帮我们布局图片。
这个插件没有提供composer安装方式,直接下载js文件并放在frontend/web/js里。
同样,也需要用asset做层包装,保证只在需要的地方引用该js。
frontend/assets/BricksAsset.php
namespace frontend\assets;
use yii\web\AssetBundle;
class BricksAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
];
public $js = [
'js/jquery-bricks.min.js',
];
public $depends = [
'yii\web\JqueryAsset',
];
}
需要注意的是,之前引用web文件夹外的资源,使用的是sourcePath,yii框架会自动帮我们复制到web文件夹下。这次文件已经在web文件夹下了,则要使用basePath,防止重复复制。
然后在首页页面注册该assetbundle,并调用我们之前写的控件。
frontend/views/site/index.php
<?php
/* @var $this yii\web\View */
use frontend\widgets\ImagePopup;
use yii\helpers\Url;
use frontend\assets\BricksAsset;
use frontend\assets\MasonryAsset;
BricksAsset::register($this);
$this->title = Yii::t('common', Yii::$app->name);
?>
<div id="container" style="font-size:0px;">
<?php
$url = Url::to(['ajax/image-popup']);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/2.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/5.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/6.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/7.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/8.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/9.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/10.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
echo ImagePopup::widget([
"options" => [
"src" => "image/thumb/11.jpg",
"dest" => $url,
"wrapDiv" => false,
]
]);
?>
</div>
<?php
$script ="$('#container').bricks();";
$script .= "$(window).resize(function() {
$('#container').data('bricks').layout();
});";
$this->registerJs($script);
?>
完成后效果及点击弹出后效果如下。