3d标签云实现过程(tagcloud.js)同步原生和 vue

写在前面

本来是没有准备写这个知识点,但是下载这个 js 的时候发现很多都是要钱或者是积分的,我就不明白了一个开源了这么久的 js 怎么还有人拿来挣钱的,同时还有一些只有原生 html 的例子,但是现在都是 框架主导的一些项目,显然是不行的,这篇文章就简单的写一下 怎么使用原生和 vue 分别使用 tagcloudjs 实现标签云,喜欢的可以直接拿去用,当然你也可以直接参考这个的例子写,我没有试过,但是 demo 是可行的tagcloudjs. 当然防止你们下载失败,我最后面会将源码贴出来,直接用就可以了,但是 vue 实现的和原生实现的 js 有一点点的差别,因为原来的 tagcloudjs 无法给 vue 使用。

结果展示

大概就是下面这个样子
在这里插入图片描述

原生代码实现
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div class="wrapper">
			<div class="tagcloud fl">
				<span id="pagetext">CSDN 玩家 1</span>
				<span id="pagetext">CSDN 玩家 2</span>
				<span id="pagetext">CSDN 玩家 3</span>
				<span id="pagetext">CSDN 玩家 4</span>
				<span id="pagetext">CSDN 玩家 5</span>
				<span id="pagetext">CSDN 玩家 6</span>
				<span id="pagetext">CSDN 玩家 7</span>
				<span id="pagetext">CSDN 玩家 8</span>
				<span id="pagetext">CSDN 玩家 9</span>
			</div>
		</div>
		<script src="../assets/js/tagcloud.js"></script>
		<script>
			tagcloud({
				selector: '.tagcloud', //元素选择器
				fontsize: 16, //基本字体大小, 单位px
				radius: 100, //滚动半径, 单位px
				mspeed: 'normal', //滚动最大速度, 取值: slow, normal(默认), fast
				ispeed: 'normal', //滚动初速度, 取值: slow, normal(默认), fast
				direction: 135, //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)...
				keep: false //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动
			});
		</script>
	</body>
	<style>
		.wrapper {
			width: 50%;
			height: 300px;
			margin: 0 auto;
			margin-top: 70px;
		}

		.tagcloud {
			position: relative;
			margin-top: 0px;
		}

		.tagcloud span {
			position: absolute;
			top: 0;
			left: 0;
			cursor: pointer;
			display: block;
			padding: 11px 30px;
			color: #60A2FF;
			font-size: 16px;
			border: 1px solid #e6e7e8;
			border-radius: 18px;
			background-color: #f2f4f8;
			text-decoration: none;
			white-space: nowrap;
			-o-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-ms-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-moz-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-webkit-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4,Direction=135, Color='#000000')";
			/*兼容ie7/8*/
			filter: progid:DXImageTransform.Microsoft.Shadow(color='#969696', Direction=125, Strength=9);
			/*strength是阴影大小,direction是阴影方位,单位为度,可以为负数,color是阴影颜色 (尽量使用数字)使用IE滤镜实现盒子阴影的盒子必须是行元素或以行元素显示(block或inline-block;)*/
		}

		.tagcloud a:hover {
			color: #3385cf;
		}
	</style>
</html>
给原生 HTML 实现用的tagcloud.js源码
/*
* 3d标签云
* 功能:鼠标移入标签,当前标签静止放大
* 说明:
* */

window.tagcloud = (function(win, doc) { // ns
    // 判断对象
    function isObject (obj) {
        return Object.prototype.toString.call(obj) === '[object Object]';
    }

    // 构造函数
    function TagCloud (options) {
        var self = this;

        self.config = TagCloud._getConfig(options);
        self.box = self.config.element;   //组件元素
        self.fontsize = self.config.fontsize; //平均字体大小
        self.radius = self.config.radius; //滚动半径
        self.depth = 2 * self.radius;   //滚动深度
        self.size = 2 * self.radius;    //随鼠标滚动变速作用区域

        self.mspeed = TagCloud._getMsSpeed(self.config.mspeed);
        self.ispeed = TagCloud._getIsSpeed(self.config.ispeed);
        self.items = self._getItems();

        self.direction = self.config.direction;   //初始滚动方向
        self.keep = self.config.keep; //鼠标移出后是否保持之前滚动

        //初始化
        self.active = false;   //是否为激活状态
        self.lasta = 1;
        self.lastb = 1;
        self.mouseX0 = self.ispeed * Math.sin(self.direction * Math.PI / 180);    //鼠标与滚动圆心x轴初始距离
        self.mouseY0 = -self.ispeed * Math.cos(self.direction * Math.PI / 180);   //鼠标与滚动圆心y轴初始距离
        self.mouseX = self.mouseX0;   //鼠标与滚动圆心x轴距离
        self.mouseY = self.mouseY0;   //鼠标与滚动圆心y轴距离
        self.index = -1;

        //鼠标移入
        TagCloud._on(self.box, 'mouseover', function () {
            self.active = true;
        });
        //鼠标移出
        TagCloud._on(self.box, 'mouseout', function () {
            self.active = false;
        });

        //鼠标在内移动
        TagCloud._on(self.keep ? win : self.box, 'mousemove', function (ev) {
            var oEvent = win.event || ev;
            var boxPosition = self.box.getBoundingClientRect();
            self.mouseX = (oEvent.clientX - (boxPosition.left + self.box.offsetWidth / 2)) / 5;
            self.mouseY = (oEvent.clientY - (boxPosition.top + self.box.offsetHeight / 2)) / 5;
        });

        for (var j = 0, len = self.items.length; j < len; j++) {
            self.items[j].element.index=j;

            //鼠标移出子元素,当前元素静止放大
            self.items[j].element.onmouseover = function(){
                self.index = this.index;
            };

            //鼠标移出子元素,当前元素继续滚动
            self.items[j].element.onmouseout = function(){
                self.index = -1;
            };
        }

        //定时更新
        TagCloud.boxs.push(self.box);
        self.update(self);    //初始更新
        self.box.style.visibility = "visible";
        self.box.style.position = "relative";
        self.box.style.minHeight = 1.2 * self.size + "px";
        self.box.style.minWidth = 2.5 * self.size + "px";
        for (var j = 0, len = self.items.length; j < len; j++) {
            self.items[j].element.style.position = "absolute";
            self.items[j].element.style.zIndex = j + 1;
        }
        self.up = setInterval(function() {
            self.update(self);
        }, 30);
    }

    //实例
    TagCloud.boxs = []; //实例元素数组
    // 静态方法们
    TagCloud._set = function (element) {
        if (TagCloud.boxs.indexOf(element) == -1) {//ie8不支持数组的indexOf方法
            return true;
        }
    };

    //添加数组IndexOf方法
    if (!Array.prototype.indexOf){
        Array.prototype.indexOf = function(elt /*, from*/){
            var len = this.length >>> 0;
            var from = Number(arguments[1]) || 0;
            from = (from < 0)
                ? Math.ceil(from)
                : Math.floor(from);
            if (from < 0)
                from += len;

            for (; from < len; from++){
                if (from in this && this[from] === elt)
                    return from;
            }
            return -1;
        };
    }


    TagCloud._getConfig = function (config) {
        var defaultConfig = {   //默认值
            fontsize: 16,       //基本字体大小, 单位px
            radius: 60,         //滚动半径, 单位px
            mspeed: "normal",   //滚动最大速度, 取值: slow, normal(默认), fast
            ispeed: "normal",   //滚动初速度, 取值: slow, normal(默认), fast
            direction: 135,     //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)...
            keep: true          //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动
        };

        if(isObject(config)) {
            for(var i in config) {
                if(config.hasOwnProperty(i)) {//hasOwnProperty()用来判断一个属性是定义在对象本身而不是继承自原型链
                    defaultConfig[i] = config[i]; //用户配置
                }
            }
        }

        return defaultConfig;// 配置 Merge
    };
    TagCloud._getMsSpeed = function (mspeed) {    //滚动最大速度
        var speedMap = {
            slow: 1.5,
            normal: 3,
            fast: 5
        };
        return speedMap[mspeed] || 3;
    };
    TagCloud._getIsSpeed = function (ispeed) {    //滚动初速度
        var speedMap = {
            slow: 10,
            normal: 25,
            fast: 50
        };
        return speedMap[ispeed] || 25;
    };
    TagCloud._getSc = function(a, b) {
        var l = Math.PI / 180;
        //数组顺序0,1,2,3表示asin,acos,bsin,bcos
        return [
            Math.sin(a * l),
            Math.cos(a * l),
            Math.sin(b * l),
            Math.cos(b * l)
        ];
    };

    TagCloud._on = function (ele, eve, handler, cap) {
        if (ele.addEventListener) {
            ele.addEventListener(eve, handler, cap);
        } else if (ele.attachEvent) {
            ele.attachEvent('on' + eve, handler);
        } else {
            ele['on' + eve] = handler;
        }
    };

    // 原型方法
    TagCloud.prototype = {
        constructor: TagCloud, // 反向引用构造器

        update: function () {
            var self = this, a, b;

            if (!self.active && !self.keep) {
                self.mouseX = Math.abs(self.mouseX - self.mouseX0) < 1 ? self.mouseX0 : (self.mouseX + self.mouseX0) / 2;   //重置鼠标与滚动圆心x轴距离
                self.mouseY = Math.abs(self.mouseY - self.mouseY0) < 1 ? self.mouseY0 : (self.mouseY + self.mouseY0) / 2;   //重置鼠标与滚动圆心y轴距离
            }

            a = -(Math.min(Math.max(-self.mouseY, -self.size), self.size) / self.radius ) * self.mspeed;
            b = (Math.min(Math.max(-self.mouseX, -self.size), self.size) / self.radius ) * self.mspeed;

            if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) { return; }

            self.lasta = a;
            self.lastb = b;

            var sc = TagCloud._getSc(a, b);

            for (var j = 0, len = self.items.length; j < len; j++) {

                var rx1 = self.items[j].x,
                    ry1 = self.items[j].y*sc[1] + self.items[j].z*(-sc[0]),
                    rz1 = self.items[j].y*sc[0] + self.items[j].z*sc[1];

                var rx2 = rx1 * sc[3] + rz1 * sc[2],
                    ry2 = ry1,
                    rz2 = rz1 * sc[3] - rx1 * sc[2];

                if(self.index==j){

                    self.items[j].scale = 1; //取值范围0.6 ~ 3
                    self.items[j].fontsize = 16;
                    self.items[j].alpha = 1;
                    self.items[j].element.style.zIndex = 99;
                }else{
                    var per = self.depth / (self.depth + rz2);
                    self.items[j].x = rx2;
                    self.items[j].y = ry2;
                    self.items[j].z = rz2;

                    self.items[j].scale = per; //取值范围0.6 ~ 3
                    self.items[j].fontsize = Math.ceil(per * 2) + self.fontsize - 6;
                    self.items[j].alpha = 1.5 * per - 0.5;
                    self.items[j].element.style.zIndex = Math.ceil(per*10-5);
                }
                self.items[j].element.style.fontSize = self.items[j].fontsize + "px";
                self.items[j].element.style.left = self.items[j].x + (self.box.offsetWidth - self.items[j].offsetWidth) / 2 + "px";
                self.items[j].element.style.top = self.items[j].y + (self.box.offsetHeight - self.items[j].offsetHeight) / 2 + "px";
                self.items[j].element.style.filter = "alpha(opacity=" + 100 * self.items[j].alpha + ")";
                self.items[j].element.style.opacity = self.items[j].alpha;
            }
        },

        _getItems: function () {
            var self = this,
                items = [],
                element = self.box.children, // children 全部是Element
                length = element.length,
                item;

            for (var i = 0; i < length; i++) {
                item = {};
                item.angle = {};
                item.angle.phi = Math.acos(-1 + (2 * i + 1) / length);
                item.angle.theta = Math.sqrt((length + 1) * Math.PI) * item.angle.phi;
                item.element = element[i];
                item.offsetWidth = item.element.offsetWidth;
                item.offsetHeight = item.element.offsetHeight;
                item.x = self.radius * 1.5 * Math.cos(item.angle.theta) * Math.sin(item.angle.phi);
                item.y = self.radius * 1.5 * Math.sin(item.angle.theta) * Math.sin(item.angle.phi);
                item.z = self.radius * 1.5 * Math.cos(item.angle.phi);
                item.element.style.left = item.x + (self.box.offsetWidth - item.offsetWidth) / 2 + "px";
                item.element.style.top = item.y + (self.box.offsetHeight - item.offsetHeight) / 2 + "px";
                items.push(item);
            }

            return items;   //单元素数组
        }



    };

    if (!doc.querySelectorAll) {//ie7不支持querySelectorAll,所以要重新定义
        doc.querySelectorAll = function (selectors) {
            var style = doc.createElement('style'), elements = [], element;
            doc.documentElement.firstChild.appendChild(style);
            doc._qsa = [];

            style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
            window.scrollBy(0, 0);
            style.parentNode.removeChild(style);

            while (doc._qsa.length) {
                element = doc._qsa.shift();
                element.style.removeAttribute('x-qsa');
                elements.push(element);
            }
            doc._qsa = null;
            return elements;
        };
    }

    return function (options) { // factory
        options = options || {}; // 短路语法
        var selector = options.selector || '.tagcloud', //默认选择class为tagcloud的元素
            elements = doc.querySelectorAll(selector),
            instance = [];
        for (var index = 0, len = elements.length; index < len; index++) {
            options.element = elements[index];
            if (!!TagCloud._set(options.element)) {
                instance.push(new TagCloud(options));
            }
        }
        return instance;
    };

})(window, document);


vue 实现
<template>
	<div class="tagcloud">
		<span v-for="i in 10">CSDN 玩家{{ i}}</span>
	</div>
</template>

<script setup>
	import { onMounted } from 'vue';
	import { tagcloud } from '../../src/assets/tagcloud.js'
	onMounted(() => {
		tagcloud({
			selector: '.tagcloud', //元素选择器
			fontsize: 16, //基本字体大小, 单位px
			radius: 100, //滚动半径, 单位px
			mspeed: 'normal', //滚动最大速度, 取值: slow, normal(默认), fast
			ispeed: 'normal', //滚动初速度, 取值: slow, normal(默认), fast
			direction: 135, //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)...
			keep: false //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动
		});
	})
</script>
  • style 同原生的一致,这里不贴代码了,避免文章太长你们看着烦
给 vue 实现用的 tagcloud.js
export const tagcloud = (function (win = window, doc = document)

将原生js 中的第一行代码改为上面的即可,将 tagcloud 导出去就可以给 vue 直接使用了,这里需要注意的一点是用的时候需要保证页面DOM 元素全部加载结束再执行 tagcloud 的方法,否则是无法加载出来的,这个和 echartsjs 用法是保持一致的,因为这些图形类的 js 使用的前提条件就是你的 DOM 元素需要存在,否则都是徒劳,当你没有效果的时候检查一下是不是 DOM 加载失败了或者是没有加载出来即可

写在后面

以上就是关于 tagcloudjs 用法的讲解了,整好最近我手里有需求需要用到这块,顺手将这个分享出去,大家用的时候有什么问题随时下面留言即可!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/178011.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Find My音箱|苹果Find My技术与音箱结合,智能防丢,全球定位

音箱市场规模正在不断扩大。随着人们生活品质的提高&#xff0c;对音乐体验的需求也在不断升级。消费者对于蓝牙音箱的需求&#xff0c;已经从单纯的音质扩展到了功能、设计和价格等多个方面。随着移动化、即时化的视听娱乐需求的增长&#xff0c;蓝牙音箱性能、质量、外观设计…

嵌入式主板购买需要考虑哪些内容?

众所周知&#xff0c;各种先进电子器件和计算机处理技术在我国自动化工业生产中的应用&#xff0c;极大地提高了发展的效率和发展水平。而嵌入式主板以其多元化的设计特点在我国工业系统的控制中表现得越来越明显&#xff0c;消费者在选择这种嵌入式主板时必须注意以下几点考虑…

2023 年 亚太赛 APMCM 国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 cs数模团队在亚太赛 APMCM前为大家提供了许多资料的内容呀&…

数学建模之拟合及其代码

发现新天地&#xff0c;欢迎访问Cr不是铬的个人网站 引言 与插值问题不同&#xff0c;在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数&#xff08;曲线&#xff09;&#xff0c;使得该曲线在某种准则下与所有的数据点最为接近&#xff0c;即曲线拟合…

JSP:Javabean

起初&#xff0c;JavaBean的目的是为了将可以重复使用的代码进行打包&#xff0c;在传统的应用中&#xff0c;JavaBean主要用于实现一些可视化界面&#xff0c;如一个窗体、按钮、文本框等&#xff0c;这样的JavaBean称之可视化的JavaBean。 随着技术的不断发展与项目的需求&am…

【前端】vue中合并表格行

做平台功能时&#xff0c;遇到一个需求是需要将表格某列有相同值时进行合并展示&#xff0c;比如 1、通过在Element中得知需要在表格中增加span-method方法 <el-table:data"tableData":span-method"cellMerge"borderstyle"width: 100%; margin-to…

Linux操作系统使用及C高级编程-D14共用体和枚举

共用体 不同数据类型可以使用共同的存储区域。和结构体的本质区别是&#xff1a;使用内存方式&#xff0c;其中共用体是使用同一块内存 1、 选择最大成员的大小 2、要能够整除成员大小&#xff0c;下图中un1中char s[7]是7个字节&#xff0c;但要遵循能整除int&#xff0c;所以…

「Docker」如何在苹果电脑上构建简单的Go云原生程序「MacOS」

介绍 使用Docker开发Golang云原生应用程序&#xff0c;使用Golang服务和Redis服务 注&#xff1a;写得很详细 为方便我的朋友可以看懂 环境部署 确保已经安装Go、docker等基础配置 官网下载链接直达&#xff1a;Docker官网下载 Go官网下载 操作步骤 第一步 创建一个…

scrapy框架流程

1、Scrapy从Spider子类中提取start_url,然后构造为request请求对象 2、将request请求对象传递给爬虫中间件 3、将request请求对象传递给Scrapy引擎&#xff08;核心代码&#xff09; 4、将request请求对象传递给调度器&#xff08;它负责对多个request安排&#xff0c;好比交…

你不知道的库:库的种类,作用和加载方式

你不知道的库&#xff1a;库的种类&#xff0c;作用和加载方式 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客…

基于单片机声光控智能路灯系统仿真设计

**单片机设计介绍&#xff0c; 基于单片机声光控智能路灯系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的声光控智能路灯系统是一种利用单片机技术实现智能控制的路灯系统。它通过感知环境音量和光照强度…

Differences between package.json and pnpm-lock.yaml

1.pnpm-lock.yaml 是pnpm包管理工具生成的确保依赖包的版本在所有的环境里面都相同对依赖包的任何操作都会更新在该文件中&#xff0c;因此&#xff0c;需要确保提交到代码仓库中。包含了解析的依赖项和版本号。如下图&#xff1a; 2.package.json 列出应用所需的依赖和元数…

深入理解Java注解的实现原理以及前世今生

深入理解Java注解的实现原理以及前世今生 小雪初寒&#xff0c;请添衣&#xff0c;冬棋如意&#xff0c;待良人&#xff0c;望归期。 1.Java注解的前世今生 Java注解是一种元数据标记&#xff0c;它提供了一种在Java代码中添加元数据&#xff08;注释&#xff09;的方式。注解…

“图纸保密大作战:上海迅软DSE解决方案守护机械公司核心资料

机械行业是我国重要的工业制造行业之一&#xff0c;相关企业在发展中往往需要用到ERP、PDM、PLM等系统来对产品信息进行管理&#xff0c;其中便涉及到大量文档和图纸等重要数据。然而随着业务的快速发展和数字化转型&#xff0c;机械行业也面临着如数据泄露、外来袭击攻击、内部…

Nuxt.js Next.js Nest.js

Nuxt.js和Next.js都是服务端渲染框架(SSR)&#xff0c;属于前端框架,Nest.js则是node框架,属于后端框架。 其中Nuxt.js是vue的ssr框架&#xff0c;Next.js是react的ssr框架。 都是比vue和react更上层的前端框架。 文章目录 1.SSR2.Nuxt2.1 Nuxt的下载2.2 Nuxt的集成2.3 Nuxt…

安装pytorch

cuda≤11.6&#xff0c;观察控制面板 观察torch对应cuda版本 https://download.pytorch.org/whl/torch/ 安装cuda11.6.0 CUDA Toolkit Archive | NVIDIA Developer cmd输入nvcc -V 编辑国内镜像源 .condarc anaconda prompt输入 查看环境 conda env list 安装py3.9…

c语言:用迭代法解决递归问题

题目&#xff1a; 解释&#xff1a;题目的意思就是用迭代法的空间和时间复杂的太高了&#xff0c;需要我们减小空间与时间的复杂度&#xff0c;我就想到了迭代法&#xff0c;思路和代码如下&#xff1a; #include <stdio.h> //这里是递归法转迭代法 int main() {int x,i…

【送书福利-第二十八期】《AIGC:让生成式AI成为自己的外脑》

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…