给友链网站加一个实时快照

钟MM的博客评论下,无意间进入到了三十里海河的一篇文章《使用 WordPress mShots 截图 API》,感觉非常的炫酷,用了一个小时,基于PIX主题的友链,更新了代码,实现了快照抓取。

原理的话参考上面的文章即可,小站实现鼠标移到网站名称或者图标上时,自动生成对应网站的首页快照,移开则消失。

注意:抓取空白或者403错误的,是对方网站做了限制抓取;显示404错误的,是对方网站已经打不开了。

三十里海河参考的是大大的小蜗牛的友链展示,本站的演示是左侧导航“互链社”。

给友链网站加一个实时快照-似水流年

废话不多说,开整。

备份pix/inc/pix-fn.php后打开,如果以前没有修改过,找到大概340行或者直接搜索“友链”。

//友链
function link_item(){
    $arr = get_op('linkscat_show');
    $linkcats = get_terms( array(
        'taxonomy'     => 'link_category',
        'include'      => $arr,
        'count'        => true,
        'hide_empty'   => 1,
        'orderby'      => 'include',
    ) );
    $output = '';
	foreach($linkcats as $linkcat){
		$id = $linkcat->term_id;
		$output .= '<div class="link_group_content"><div class="link_cat_name"><i class="ri-bookmark-line"></i>'.$linkcat->name.'</div><div id="link_'.$id.'" class="link_group">';
			$bookmarks = get_bookmarks( 'orderby=date&category='.$id);
			if ( !empty($bookmarks) ) {
				foreach ( $bookmarks as $bookmark ) {
					$img_type = $bookmark->link_image ? $bookmark->link_image : '';
					$preg = "/^http(s)?:\\/\\/.+/";
                    $avatar = '<img src="'.THEME_URL.'/img/avatar.png">';
                    if(!empty($img_type)){
                        if ( preg_match($preg,@$img_type) ) {
                            $avatar = '<img alt="avatar" src="'. $bookmark->link_image .'" srcset="'. $bookmark->link_image .'" class="avatar avatar-80" height="80" width="80">';
                        }
                        else {
                            $avatar = get_avatar( $bookmark->link_image, 80 );
                        }
                    }
					
					$output .= '<div class="item" title="'. $bookmark->link_description .'">';
					$output .= '<div class="link-avatar"><a href="'. $bookmark->link_url .'" target="_blank">'. $avatar .'</a></div>';
					$output .= '<div class="info">';
					$output .= '<h3 class="name"><a href="'. $bookmark->link_url .'" target="_blank">'. $bookmark->link_name .'</a></h3>';
					$output .= '<div class="meta button"><a href="'. $bookmark->link_url .'" target="_blank"><i class="iconfont icon-zhuanfa_3"></i></a></div>';
					$output .= '<div class="description">'. $bookmark->link_description .'</div></div>';
					$output .= '</div>';
				}
			}
			$output .= '</div></div>';
	}

    return $output;
   
}

一、如果全站未启用PJAX,把这段修改成如下代码:

[reply]

// 友链
function link_item(){
    $arr = get_op('linkscat_show');
    $linkcats = get_terms( array(
        'taxonomy'     => 'link_category',
        'include'      => $arr,
        'count'        => true,
        'hide_empty'   => 1,
        'orderby'      => 'include',
    ) );
    $output = '';
    foreach($linkcats as $linkcat){
        $id = $linkcat->term_id;
        $output .= '<div class="link_group_content"><div class="link_cat_name"><i class="ri-bookmark-line"></i>'.$linkcat->name.'</div><div id="link_'.$id.'" class="link_group">';
            $bookmarks = get_bookmarks( 'orderby=date&category='.$id);
            if ( !empty($bookmarks) ) {
                foreach ( $bookmarks as $bookmark ) {
                    $img_type = $bookmark->link_image ? $bookmark->link_image : '';
                    $preg = "/^http(s)?:\\/\\/.+/";
                    $avatar = '<img src="'.THEME_URL.'/img/avatar.png">';
                    if(!empty($img_type)){
                        if ( preg_match($preg,@$img_type) ) {
                            $avatar = '<img alt="avatar" src="'. $bookmark->link_image .'" srcset="'. $bookmark->link_image .'" class="avatar avatar-80" height="80" width="80">';
                        } else {
                            $avatar = get_avatar( $bookmark->link_image, 80 );
                        }
                    }

                    $output .= '<div class="item" title="'. $bookmark->link_description .'">';
                    $output .= '<div class="link-avatar"><a href="'. $bookmark->link_url .'" target="_blank" class="hover-trigger">'. $avatar .'</a></div>';
                    $output .= '<div class="info">';
                    $output .= '<h3 class="name"><a href="'. $bookmark->link_url .'" target="_blank" class="hover-trigger">'. $bookmark->link_name .'</a></h3>';
                    $output .= '<div class="meta button"><a href="'. $bookmark->link_url .'" target="_blank"><i class="iconfont icon-zhuanfa_3"></i></a></div>';
                    $output .= '<div class="description hover-trigger">'. $bookmark->link_description .'</div></div>';
                    $output .= '</div>';
                }
            }
            $output .= '</div></div>';
    }

    // Add custom script to handle the hover functionality with optimizations
    $output .= '
    <style>
        .hover-preview {
            position: absolute;
            width: 400px;
            height: 320px;
            display: none;
            border: 1px solid #ddd;
            box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
            z-index: 1000;
        }
    </style>
    <script>
        document.addEventListener("DOMContentLoaded", function(){
            const hoverTriggers = document.querySelectorAll(".hover-trigger");
            let preview = document.createElement("img");
            preview.className = "hover-preview";
            document.body.appendChild(preview);

            hoverTriggers.forEach(trigger => {
                let debounceTimer;
                
                trigger.addEventListener("mouseover", function(e) {
                    const url = e.target.closest("a").href;
                    const previewUrl = `https://s0.wordpress.com/mshots/v1/` + encodeURIComponent(url) + `?w=400&h=320`;

                    // Load the preview image only if it is not already loaded
                    if (preview.src !== previewUrl) {
                        preview.src = previewUrl;
                    }
                    preview.style.display = "block";
                });

                trigger.addEventListener("mousemove", function(e) {
                    clearTimeout(debounceTimer);
                    debounceTimer = setTimeout(function() {
                        let previewX = e.pageX + 2;
                        let previewY = e.pageY + 2;

                        // Ensure the preview image stays within the viewport
                        if (previewX + preview.width > window.innerWidth) {
                            previewX = e.pageX - preview.width - 2;
                        }

                        if (previewY + preview.height > window.innerHeight) {
                            previewY = e.pageY - preview.height - 2;
                        }

                        preview.style.left = previewX + "px";
                        preview.style.top = previewY + "px";
                    }, 50); // Adjust the debounce delay as needed
                });

                trigger.addEventListener("mouseout", function() {
                    preview.style.display = "none";
                });
            });
        });
    </script>';

    return $output;
}

[/reply]

二、如果全站启用了PJAX,把这段修改成如下代码:

[reply]

// 友链
function link_item(){
    $arr = get_op('linkscat_show');
    $linkcats = get_terms( array(
        'taxonomy'     => 'link_category',
        'include'      => $arr,
        'count'        => true,
        'hide_empty'   => 1,
        'orderby'      => 'include',
    ) );
    $output = '';
    foreach($linkcats as $linkcat){
        $id = $linkcat->term_id;
        $output .= '<div class="link_group_content"><div class="link_cat_name"><i class="ri-bookmark-line"></i>'.$linkcat->name.'</div><div id="link_'.$id.'" class="link_group">';
            $bookmarks = get_bookmarks( 'orderby=date&category='.$id);
            if ( !empty($bookmarks) ) {
                foreach ( $bookmarks as $bookmark ) {
                    $img_type = $bookmark->link_image ? $bookmark->link_image : '';
                    $preg = "/^http(s)?:\\/\\/.+/";
                    $avatar = '<img src="'.THEME_URL.'/img/avatar.png">';
                    if(!empty($img_type)){
                        if ( preg_match($preg,@$img_type) ) {
                            $avatar = '<img alt="avatar" src="'. $bookmark->link_image .'" srcset="'. $bookmark->link_image .'" class="avatar avatar-80" height="80" width="80">';
                        } else {
                            $avatar = get_avatar( $bookmark->link_image, 80 );
                        }
                    }

                    $output .= '<div class="item" title="'. $bookmark->link_description .'">';
                    $output .= '<div class="link-avatar"><a href="'. $bookmark->link_url .'" target="_blank" class="hover-trigger">'. $avatar .'</a></div>';
                    $output .= '<div class="info">';
                    $output .= '<h3 class="name"><a href="'. $bookmark->link_url .'" target="_blank" class="hover-trigger">'. $bookmark->link_name .'</a></h3>';
                    $output .= '<div class="meta button"><a href="'. $bookmark->link_url .'" target="_blank"><i class="iconfont icon-zhuanfa_3"></i></a></div>';
                    $output .= '<div class="description hover-trigger">'. $bookmark->link_description .'</div></div>';
                    $output .= '</div>';
                }
            }
            $output .= '</div></div>';
    }

    // Add custom script to handle the hover functionality with optimizations
    $output .= '
    <style>
        .hover-preview {
            position: absolute;
            width: 400px;
            height: 320px;
            display: none;
            border: 1px solid #ddd;
            box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
            z-index: 1000;
        }
    </style>
    <script>
        function initializeHoverPreview() {
            const hoverTriggers = document.querySelectorAll(".hover-trigger");
            let preview = document.querySelector(".hover-preview");

            if (!preview) {
                preview = document.createElement("img");
                preview.className = "hover-preview";
                document.body.appendChild(preview);
            }

            hoverTriggers.forEach(trigger => {
                let debounceTimer;

                trigger.addEventListener("mouseover", function(e) {
                    const url = e.target.closest("a").href;
                    const previewUrl = `https://s0.wordpress.com/mshots/v1/` + encodeURIComponent(url) + `?w=400&h=320`;

                    if (preview.src !== previewUrl) {
                        preview.src = previewUrl;
                    }
                    preview.style.display = "block";
                });

                trigger.addEventListener("mousemove", function(e) {
                    clearTimeout(debounceTimer);
                    debounceTimer = setTimeout(function() {
                        let previewX = e.pageX + 2;
                        let previewY = e.pageY + 2;

                        if (previewX + preview.width > window.innerWidth) {
                            previewX = e.pageX - preview.width - 2;
                        }

                        if (previewY + preview.height > window.innerHeight) {
                            previewY = e.pageY - preview.height - 2;
                        }

                        preview.style.left = previewX + "px";
                        preview.style.top = previewY + "px";
                    }, 50);
                });

                trigger.addEventListener("mouseout", function() {
                    preview.style.display = "none";
                });
            });
        }

        document.addEventListener("DOMContentLoaded", initializeHoverPreview);
        document.addEventListener("pjax:end", initializeHoverPreview);
    </script>';

    return $output;
}

同时,修改pix/inc/assets/js/app.js,大概第1436行:

//pjax
if(Theme.pjax){
    $(document).pjax('a[pjax!=exclude][target!=_blank]', '#pjax-container', { // .page 需要刷新的 DIV 部分的类名
        fragment: '#pjax-container',
        timeout: 8000,
    }).on('pjax:complete', function() {
        lazyLoadInstance.update();
        hljs.highlightAll();
        autoload_topic();
        autoload_posts();       
        autoload_posts_music();
    });
    
    $(document).on('pjax:start', function() { NProgress.start(); });
    $(document).on('pjax:end',   function() { NProgress.done(); });
}

修改为:

//pjax
if(Theme.pjax){
    $(document).pjax('a[pjax!=exclude][target!=_blank]', '#pjax-container', { // .page 需要刷新的 DIV 部分的类名
        fragment: '#pjax-container',
        timeout: 8000,
    }).on('pjax:complete', function() {
        lazyLoadInstance.update();
        hljs.highlightAll();
        autoload_topic();
        autoload_posts();       
        autoload_posts_music();
        initializeHoverPreview();

    });
    
    $(document).on('pjax:start', function() { NProgress.start(); });
    $(document).on('pjax:end',   function() { NProgress.done(); });
}

function initializeHoverPreview() {
    const hoverTriggers = document.querySelectorAll(".hover-trigger");
    let preview = document.querySelector(".hover-preview");

    if (!preview) {
        preview = document.createElement("img");
        preview.className = "hover-preview";
        document.body.appendChild(preview);
    }

    hoverTriggers.forEach(trigger => {
        let debounceTimer;

        trigger.addEventListener("mouseover", function(e) {
            const url = e.target.closest("a").href;
            const previewUrl = `https://s0.wordpress.com/mshots/v1/` + encodeURIComponent(url) + `?w=400&h=320`;

            if (preview.src !== previewUrl) {
                preview.src = previewUrl;
            }
            preview.style.display = "block";
        });

        trigger.addEventListener("mousemove", function(e) {
            clearTimeout(debounceTimer);
            debounceTimer = setTimeout(function() {
                let previewX = e.pageX + 2;
                let previewY = e.pageY + 2;

                if (previewX + preview.width > window.innerWidth) {
                    previewX = e.pageX - preview.width - 2;
                }

                if (previewY + preview.height > window.innerHeight) {
                    previewY = e.pageY - preview.height - 2;
                }

                preview.style.left = previewX + "px";
                preview.style.top = previewY + "px";
            }, 50);
        });

        trigger.addEventListener("mouseout", function() {
            preview.style.display = "none";
        });
    });
}

[/reply]

其中以上代码,width: 400px和height: 320px是生成快照的长和宽,根据自己需要修改。

搞定收工!

Comments | 2 条评论
  • 奶爸

    Microsoft Edge 119 Microsoft Edge 119 Windows 10 Windows 10 1中国–上海–上海 电信/电信CN2 ip address 58.32.*.*

    真棒,如果加载能再快点那就更完美了。

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国–河南–漯河 电信 ip address 222.89.*.*

      核心还是引用下面网址https://s0.wordpress.com/mshots/v1/
      所以速度应该提不上去。

消息盒子
# 您需要首次评论以获取消息 #
# 您需要首次评论以获取消息 #

只显示最新10条未读和已读信息