css滑行轨迹_滑行:轻松动态按需调整图像大小

css滑行轨迹

Glide kayaks image

Glide is an image processing library built on top of Intervention. Its purpose is to facilitate on-demand image processing. That’s a fancy way of saying it creates images as they’re requested if they don’t exist.

Glide是建立在Intervention之上的图像处理库。 其目的是促进按需图像处理。 这是一种奇特的说法,即如果图像不存在,它会根据要求创建图像。

For example, you might have a large, high quality portrait for your user profile. But when opening on a mobile device, downloading a 10 MB image is not only wasteful, it is slow. Instead, you could add a media query into your CSS, like so:

例如,您的用户个人资料可能有一个大型的高质量肖像。 但是,在移动设备上打开时,下载10 MB的映像不仅浪费,而且很慢。 相反,您可以在CSS中添加媒体查询,如下所示:

@media (min-width: 400px) {
	.profilePic {
		background-image: url('/images/myprofile.jpg');	
	}
}

@media (max-width: 400px) {
    .profilePic {
		background-image: url('/images/myprofile-320.jpg');			
	}
}

This would make all devices under 400px of width load the smaller background image, thus downloading faster. But manually resizing every image you might need in your app is tedious, time consuming, and error prone. That’s where Glide comes in.

这将使宽度小于400像素的所有设备加载较小的背景图片,从而加快下载速度。 但是,手动调整应用程序中可能需要的每个图像的大小是繁琐,耗时且容易出错的。 那就是Glide进来的地方。

Glide can be configured to respond to missing image requests (such as the non-existant myprofile-320.jpg from the example above) by creating them from a predetermined source. In a nutshell, if the requested image doesn’t exist, but its source does, the requested image gets created from it. What’s more, the image can be saved into a cache, so that future requests don’t invoke the library and waste precious CPU resources on re-rendering.

可以将Glide配置为通过从预定来源创建缺失的图像请求(例如上例中不存在的myprofile-320.jpg )进行响应。 简而言之,如果所请求的图像不存在,但其源存在,则从中创建所请求的图像。 此外,可以将图像保存到缓存中,以便将来的请求不会调用该库并在重新渲染时浪费宝贵的CPU资源。

Let’s configure it.

让我们对其进行配置。

If you’d like to follow along, feel free to use our no-framework application and Homestead Improved for quickly setting up an environment and sample application to test this in.

如果您想继续学习,请随时使用我们的无框架应用程序Homestead改良版,以快速设置环境和示例应用程序进行测试。

自举 (Bootstrapping)

Step one is installing Glide:

第一步是安装Glide:

composer require league/glide

Then, we need to configure the Glide server. In the NOFW project above, this happens in app/config.php where all the services are configured for future injection via PHP-DI. This is how it’s done:

然后,我们需要配置Glide服务器。 在上面的NOFW项目中,这发生在app/config.php ,其中所有服务都配置为将来通过PHP-DI注入。 这是这样做的:

// ...

    'glide' => function () {
        $server = League\Glide\ServerFactory::create(
            [
                'source' => new League\Flysystem\Filesystem(
                    new League\Flysystem\Adapter\Local(
                        __DIR__ . '/../assets/image'
                    )
                ),
                'cache' => new League\Flysystem\Filesystem(
                    new League\Flysystem\Adapter\Local(
                        __DIR__ . '/../public/static/image'
                    )
                ),
                'driver' => 'gd',
            ]
        );

        return $server;
    },

// ...

Now we can push (or pull) the glide instance into a controller when needed. The source and cache values determine where original images are found, and where generated images should be stored respectively, while the driver key specifies that the built-in PHP GD image manipulation extension should be used to modify the images.

现在,我们可以在需要时将glide实例推入(或拉入)控制器。 source值和cache值确定分别在哪里找到原始图像以及应在何处存储生成的图像,而driver键指定应使用内置PHP GD图像操作扩展名来修改图像。

You should alter the image paths to apply to your own.

您应该更改图像路径以应用于自己的图像路径。

While these are the main ones, there are many other settings, too – feel free to study them at your own leisure.

尽管这些是主要设置 ,但还有许多其他设置 –您可以随时休闲学习它们。

路由 (Routing)

Next, we need to define a route which will get triggered when an image which does not exist is requested. The no-framework application uses fastRoute, so defining the route is as simple as adding the following into app/routes.php:

接下来,我们需要定义一条路由,当请求不存在的图像时将触发该路由。 无框架应用程序使用fastRoute ,因此定义路由就像将以下内容添加到app/routes.php routes.php一样简单:

['GET', '/static/image/{image}', ['MyControllers\Controllers\ImageController', 'renderImage']]

What ever {image} in the route evaluates to will get passed as $image to the renderImage method of ImageController (which we will write next).

路由中经过{image}计算的对象将作为$image传递到ImageControllerrenderImage方法(我们将在下面编写)。

处理中 (Processing)

Let’s build the ImageController now:

让我们现在构建ImageController

<?php

namespace MyControllers\Controllers;

use League\Glide\Server;
use Standard\Abstracts\Controller;

class ImageController extends Controller
{
    /**
     * @Inject("glide")
     * @var Server
     */
    private $glide;

    public function renderImage($image)
    {
        $width = $this->getWidth($image);

        $imageSource = str_replace('-'.$width, '', $image);
        $this->glide->outputImage($imageSource, ['w' => $width]);
    }

    /**
     * @param string $imagePath
     * @return int
     */
    private function getWidth(string $imagePath) : int
    {
        $fragments = explode('-', $imagePath);
        return (int)explode('.', $fragments[1])[0];
    }
}

The Glide server instance is automatically injected into the controller with PHP-DI’s @Inject annotation. If this is confusing or interesting, please see the documentation. Then, renderImage is given the image path, calls the internal getWidth method which extracts the width from the image name, and finally resizes and renders the image.

Glide服务器实例将使用PHP-DI的@Inject注释自动注入到控制器中。 如果这令人困惑或有趣,请参阅文档 。 然后,为renderImage提供图像路径,调用内部getWidth方法,该方法从图像名称中提取宽度,最后调整大小并呈现图像。

Note that we’re not using $_GET params for passing in resize settings as per Glide docs – this is because I prefer my image URLs to look like real URLs to static resources, so that they can later be used as actual static resources.

请注意,根据Glide docs,我们没有使用$ _GET参数来传递调整大小设置-这是因为我更喜欢图像URL看起来像静态资源的真实URL,以便以后可以用作实际的静态资源。

This works, but astute readers might notice a problem…

这行得通,但是精明的读者可能会注意到一个问题……

固定 (Securing)

As it is, the application is vulnerable to mass-image-editing attacks. Someone could write a loop of thousands of different image sizes, slap them onto every image they can harvest from your website, and make your server convert to arbitrary and pointless sizes 24/7. The Glide docs recommend signing the URL so that only authorized URLs pass, but this is both complicated and very difficult to achieve when dealing with external stylesheets. We’d have to pre-process our CSS and regenerate all image URLs inside it – a complex procedure made even more complicated by the fact that we probably have some other, unrelated front end asset compilation steps, too (for that, see here).

实际上,该应用程序容易受到大众图像编辑攻击。 有人可以编写成千上万个不同大小的图像的循环,将它们拍打到可以从您的网站上收获的每个图像上,并使您的服务器转换为24/7的任意和毫无意义的尺寸。 Glide文档建议对URL进行签名,以便仅授权的URL通过,但这既复杂又很难在处理外部样式表时实现。 我们必须预处理CSS并重新生成其中的所有图像URL-由于我们可能还有其他一些不相关的前端资产编译步骤,这一复杂过程变得更加复杂(为此,请参见此处 ) 。

The right approach is, instead, to limit the sizes to which images can be resized with either routes or specific rules. Since we only have one route which leads to our images, let’s take the latter approach – allowing only specific sizes to be generated right there in the processing logic.

相反,正确的方法是使用路由或特定规则限制可调整图像大小的大小。 由于我们只有一条通往图像的路线,因此我们采用后一种方法–在处理逻辑中仅允许生成特定的尺寸。

<?php

namespace MyControllers\Controllers;

use League\Glide\Server;
use Standard\Abstracts\Controller;

class ImageController extends Controller
{
    /**
     * @Inject("glide")
     * @var Server
     */
    private $glide;

    private $allowedWidths = [
        320,
        768,
        992,
        1280,
        1920,
    ];

    public function renderImage($image)
    {
        $width = $this->getWidth($image);

        $imageSource = str_replace('-'.$width, '', $image);
        $this->glide->outputImage($imageSource, ['w' => $width]);
    }

    /**
     * @param string $imagePath
     * @return int
     */
    private function getWidth(string $imagePath) : int
    {
        $fragments = explode('-', $imagePath);

        if (count($fragments) < 2) {
            header(
                ($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0') . ' 500 ' . 'Server Error ImgErr00'
            );
            die("Nope! Image fragments missing.");
        }

        $width = (int)explode('.', $fragments[1])[0];
        if (!in_array($width, $this->allowedWidths)) {
            header(
                ($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0') . ' 500 ' . 'Server Error ImgErr01'
            );
            die("Nope! Disallowed width.");
        }

        return $width;
    }
}

The getWidth method was extended with some primitive checks – the first to make sure the image has a size extension (so no more generating original-size images! – that saves bandwidth, too) – and the second to make sure the size is allowed, by comparing it to the $allowedWidths array property in the controller.

通过一些原始检查扩展了getWidth方法-第一个检查以确保图像具有尺寸扩展名(这样就不再生成原始尺寸的图像!也可以节省带宽)-第二个以确保允许尺寸,通过将其与控制器中的$allowedWidths数组属性进行比较。

Naturally, this can be extended with heights, sizing mode, and all the other Glide options on offer.

自然,可以使用高度,尺寸调整模式以及所有其他Glide选项扩展该功能。

关于使用Glide进行保存的注意事项 (A Note on Saving with Glide)

Our images are now being safely resized and rendered.

现在,我们可以安全地调整图像大小并进行渲染。

Unfortunately, Glide is “PHP only” in that it is not possible to have a server point to an image directly after it’s been generated. This is because the generated images always looks like this:

不幸的是,Glide是“仅PHP”,因为不可能在图像生成后直接将服务器指向图像。 这是因为生成的图像始终如下所示:

- images/
   - myprofile.jpg/
       lhgn3q489uncdue7b9qdny98xq3

… rather than the requested myprofile-320.jpg. The image name will actually be the folder, and the image will be an anonymous file in that folder. This means that in order to get back the myprofile-320.jpg image, PHP will always have to invoke Glide, which will always have to check if the image exists and then serve it, or generate it if it doesn’t.

…而不是要求的myprofile-320.jpg 。 图像名称实际上是该文件夹,而该图像将是该文件夹中的匿名文件。 这意味着,为了取回myprofile-320.jpg图像,PHP将始终必须调用Glide,后者将始终必须检查该图像是否存在然后提供服务,或者生成不存在的图像。

Generally, this isn’t a dealbreaker due to the images being served with extra long-lasting headers:

通常,由于图像带有额外的持久标题,因此这不是一个大问题:

header('Cache-Control:'.'max-age=31536000, public');
        header('Expires:'.date_create('+1 years')->format('D, d M Y H:i:s').' GMT');

… and the fact that a single PHP request to serve an image before, again, using those super long expiry headers, isn’t that much of an overhead, but is something you might want to keep in mind when planning that next high traffic app. The situation can further be improved by putting a pull zone in front of everything, and even a more powerful caching server like Varnish, but that’s a story for another day.

…事实是,单个PHP请求再次使用这些超长的到期标头来提供图像,这并不会带来太多的开销,但是在计划下一个高流量应用时,您可能需要牢记这一点。 可以通过在所有内容甚至是更强大的缓存服务器(如Varnish)前面放置一个拉区来进一步改善这种情况,但这又是另一回事了。

或者... (Alternatively…)

To completely bypass the PHP cycle in the subsequent renders, you could do something like this:

要完全绕过后续渲染中PHP周期,您可以执行以下操作:

public function renderImage($image)
    {
        $width = $this->getWidth($image);

        $imageSource = str_replace('-'.$width, '', $image);

        $imagePath = $this->glide->makeImage($imageSource, ['w' => $width]);
        $imageBase = $this->glide->getCache()->read($imagePath);
        $this->glide->getCache()->put($image, $imageBase);
        $this->glide->outputImage($imageSource, ['w' => $width]);
    }

makeImage creates and saves the image, but returns only its path. We then read the image’s contents with said path from the cache. Finally, we re-save the image under its originally requested name, and then output like we did before. Thus, only this first call will be expensive (several I/O operations and a conversion), and all future calls to this image URL will go straight to the image – bypassing PHP completely. In fact, if you power down PHP with sudo service php-fpm stop, the image will still load.

makeImage创建并保存图像,但仅返回其路径。 然后,我们从缓存中读取具有所述路径的图像内容。 最后,我们以原始请求的名称重新保存图像,然后像以前一样输出。 因此,只有第一个调用会很昂贵(几次I / O操作和一次转换),以后所有对该图像URL的调用都将直接转到该图像-完全绕过PHP。 实际上,如果使用sudo service php-fpm stop关闭PHP的电源,则图像仍会加载。

结论 (Conclusion)

In this tutorial, we looked at the ease of use of Glide, an image manipulation package which can generate modified images on-demand, saving you the trouble of having to generate them before deploying your application.

在本教程中,我们研究了Glide的易用性,它是一种图像处理程序包,可以按需生成修改后的图像,从而省去了在部署应用程序之前必须生成它们的麻烦。

Are you using Glide? An alternative approach perhaps? Let us know!

您正在使用Glide吗? 也许是替代方法? 让我们知道!

翻译自: https://www.sitepoint.com/easy-dynamic-on-demand-image-resizing-with-glide/

css滑行轨迹

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值