38

我最近收到了来自 Onnit Labs 的电子邮件,其中包含使用 gif 图像的电子邮件内的倒计时模块计时器。可以在此处查看电子邮件:https ://www.onnit.com/emails/lastchance-historic/

图片可以在这里看到:

在此处输入图像描述

我调查了一下,似乎您可以使用 gifsockets 继续向动画 GIF 发送新帧,因为 GIF 没有指定在浏览器中加载时它有多少帧。它在 github 上:http: //github.com/videlalvaro/gifsockets

我认为这很有趣,而且效果确实很酷。有没有人对如何实现这一点有任何其他见解?似乎他们在 Onnit 使用的那个似乎根据 URL 或图像末尾附加的日期更改了倒计时。

onnit.com/emails/_modules/timer/?end=2012-12-27+00:00:00&dark=1

我正在尝试完成相同的事情以发送电子邮件,但我有点难过。

4

4 回答 4

37

虽然可能gifsockets会起作用(我之前没有尝试过......),但在我查看图像时没有网络流量,而不是初始图像加载。我也看到它再次从 41 跳到 42。重新加载将其降至 39。

它似乎只是一个脚本,可以生成 60 帧动画并将它们发送给用户。这可能可以用任何语言完成。

以下是它在 php 中的实现方式:

http://seanja.com/secret/countdown/

在此处输入图像描述

于 2012-11-28T03:25:39.590 回答
4

我发现http://sendtric.com/是免费的,而且很容易集成。

于 2016-12-11T12:56:55.867 回答
0

你可以试试http://makedreamprofits.com/pt/。这个倒计时不是为 gif 提供额外的内容,而是分成单独的图像,并且可以计数长达 20 分钟而不会增加太多流量。

PS Gmail 正在预缓存图像,因此无法无休止地为其提供新帧。

于 2018-06-03T09:32:56.990 回答
0

我非常感谢 Sean Ja 的回答。(他应该得到更多的支持。)然后我想让代码更具可读性和可配置性(并支持透明 gif 上的文本并自动居中文本):

use Carbon\Carbon;
class CountdownGifHelper {

    const DELAY = 100; /* Why was this labeled as 'milliseconds' when it seems like a value of 100 here causes 1 frame to be shown per second? */
    const MAX_FRAMES = 120;

    /**
     * 
     * @param string $bgImg
     * @param \DateInterval $interval
     * @param array $fontArr
     * @param array $frames
     * @param array $delays
     * @param string $format
     */
    public function addFrame($bgImg, $interval, $fontArr, &$frames, &$delays, $format) {
        $image = imagecreatefrompng($bgImg); //Each frame needs to start by creating a new image because otherwise the new numbers would draw on top of old ones. Here, it doesn't really matter what the PNG is (other than for size) because it's about to get filled with a new color.
        $text = $interval->format($format);
        ob_start();
        imageSaveAlpha($image, true);
        $backgroundColor = $fontArr['backgroundColor'];
        imagefill($image, 0, 0, $backgroundColor); //https://stackoverflow.com/a/17016252/470749 was a helpful hint
        imagecolortransparent($image, $backgroundColor);
        $this->insertCenteredText($image, $fontArr, $text);
        //imagettftext($image, $font['size'], $font['angle'], $font['x-offset'], $font['y-offset'], $font['color'], $font['file'], $text);//this was the old way
        imagegif($image); //The image format will be GIF87a unless the image has been made transparent with imagecolortransparent(), in which case the image format will be GIF89a.
        $frames[] = ob_get_contents();
        ob_end_clean();
        $delays[] = self::DELAY;
    }

    /**
     * 
     * @param resource $image
     * @param array $fontArray
     * @param string $text
     */
    public function insertCenteredText(&$image, $fontArray, $text) {
        $image_width = imagesx($image);
        $image_height = imagesy($image);
        $text_box = imagettfbbox($fontArray['size'], $fontArray['angle'], $fontArray['file'], $text); // Get Bounding Box Size
        $text_width = $text_box[2] - $text_box[0];
        $text_height = $text_box[7] - $text_box[1];
        // Calculate coordinates of the text https://stackoverflow.com/a/14517450/470749
        $x = ($image_width / 2) - ($text_width / 2);
        $y = ($image_height / 2) - ($text_height / 2);
        imagettftext($image, $fontArray['size'], $fontArray['angle'], $x, $y, $fontArray['color'], $fontArray['file'], $text);
    }

    /**
     * 
     * @param int $timestamp
     * @param string $bgImg
     * @param array $fontArray
     * @return string [can be used by Laravel response()->make($gifString, 200, $headers)]
     */
    public function getAnimatedGif($timestamp, $bgImg, $fontArray) {
        $future_date = Carbon::createFromTimestamp($timestamp);
        $time_now = time();
        $moment = new \DateTime(date('r', $time_now));
        $frames = [];
        $delays = [];
        for ($i = 0; $i <= self::MAX_FRAMES; $i++) {
            $interval = date_diff($future_date, $moment);
            if ($future_date < $moment) {
                $this->addFrame($bgImg, $interval, $fontArray, $frames, $delays, '00 : 00 : 00');
                $loops = 1; //stay stuck on this frame
                break;
            } else {
                $this->addFrame($bgImg, $interval, $fontArray, $frames, $delays, '%H : %I : %S');
                $loops = 0; //infinite loop
            }
            $moment->modify('+1 second');
        }
        $animatedGif = new \App\Helpers\AnimatedGif($frames, $delays, $loops, 0, 0, 0);
        return $animatedGif->getAnimation();
    }

    /**
     * ONEDAY allow config via params
     * @param resource $image
     * @return array
     */
    public function getFontArray($image) {
        $fontArr = [
            'file' => resource_path('assets/fonts/Kanit-Regular.ttf'),
            'size' => 30,
            //'x-offset' => 5,
            //'y-offset' => 30,
            'color' => imagecolorallocate($image, 90, 90, 90), //gray
            'backgroundColor' => imagecolorallocate($image, 0, 0, 0), //white. Must match the arguments provided to AnimatedGif (such as 0,0,0).
            'angle' => 0,
        ];
        return $fontArr;
    }

}
于 2019-10-05T17:06:22.040 回答