{"id":16385344,"url":"https://github.com/any86/any-scroll","last_synced_at":"2025-03-16T16:31:03.039Z","repository":{"id":45403245,"uuid":"179781749","full_name":"any86/any-scroll","owner":"any86","description":":rocket: 模拟scrollview, 支持pc/移动端, 让实现Tab/Slider等组件轻而易举.","archived":false,"fork":false,"pushed_at":"2023-10-17T15:05:58.000Z","size":26499,"stargazers_count":55,"open_issues_count":9,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-16T03:51:13.858Z","etag":null,"topics":["requestanimationframe","scroll","scrollview","vue"],"latest_commit_sha":null,"homepage":"https://any86.github.io/any-scroll/index.prod.html","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/any86.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-06T02:55:00.000Z","updated_at":"2025-03-05T11:10:14.000Z","dependencies_parsed_at":"2024-06-20T22:09:30.849Z","dependency_job_id":null,"html_url":"https://github.com/any86/any-scroll","commit_stats":{"total_commits":231,"total_committers":1,"mean_commits":231.0,"dds":0.0,"last_synced_commit":"ac86fd337a823161933ad6a24ec52b93ab7de810"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/any86%2Fany-scroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/any86%2Fany-scroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/any86%2Fany-scroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/any86%2Fany-scroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/any86","download_url":"https://codeload.github.com/any86/any-scroll/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243822284,"owners_count":20353499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["requestanimationframe","scroll","scrollview","vue"],"created_at":"2024-10-11T04:14:17.972Z","updated_at":"2025-03-16T16:31:02.742Z","avatar_url":"https://github.com/any86.png","language":"TypeScript","readme":"# any-scroll [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![size-image]][size-url] \n\n[size-image]: https://badgen.net/bundlephobia/minzip/any-scroll\n[size-url]: https://bundlephobia.com/result?p=any-scroll\n[npm-image]: https://badgen.net/npm/v/any-scroll\n[npm-url]: https://npmjs.org/package/any-scroll\n[downloads-image]: https://badgen.net/npm/dt/any-scroll\n[downloads-url]: https://npmjs.org/package/any-scroll\n\n模拟滚动插件,支持滚轮和手势, 手势识别基于[any-touch](https://github.com/any86/any-touch).\n\n## 概念(wrap/content)\nany-scroll的滚动实际是通过2个\"**父子div**\"的相对位置变化模拟的, 默认使用translate3d, 外层div叫\"**wrap**\", 里面用来装载内容的div叫\"**content**\".\n```html\n\n\u003cdiv\u003e \u003c!-- warp --\u003e \n    \u003cdiv\u003e \u003c!-- content --\u003e\n        content\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\n![GIF](https://user-images.githubusercontent.com/8264787/146702700-304115ca-55ef-46b9-85d6-d6c3fa02683c.gif)\n\n### ⚡⚡⚡ 多个content\n如果wrap下有多个元素, 那么any-scroll会把他们都构造成content实例, 但是只有一个\"**激活**\"状态的content实例, 只有他可以响应滚动, 当然你也可以切换任意content实例为[激活](#active).\n```html\n\u003c!-- warp --\u003e \n\u003cdiv\u003e \n    \u003c!-- content --\u003e\n    \u003cdiv\u003econtent-1\u003cdiv\u003e \n\n    \u003c!-- content --\u003e\n    \u003cdiv style=\"position: absolute;z-index:1;top:0;left:0;\"\u003e\n        content-2\n    \u003cdiv\u003e \n    \n    \u003c!-- content --\u003e\n    \u003cdiv no-scroll\u003econtent-3\u003cdiv\u003e \n\u003c/div\u003e\n```\n**注意**: \n1. 多个content情况下, 请给第二个子元素做一个\"初始定位\", 比如`style=\"position: absolute;z-index:1;top:0;left:0;\"`, any-scroll内部没有默认定位, 这样你可以自定义\"位置\"和\"层级\".\n2. 如果不想某个子元素(content)\"可滚动\", 使用\"**no-scroll**\"进行标记. \n\n[🚀返回目录](#目录)\n\n\n## 目录\n- [概念](#概念wrapcontent)\n- [安装](#安装)\n- [使用](#使用)\n- [API](#API)\n    - [选项](#选项)\n    - [实例属性](#实例属性)\n        - [el : wrap元素](#el)\n        - [size : wrap元素尺寸](#size)\n        - [at : any-touch实例](#at)\n    - [实例方法](#实例方法)\n        - [on : 监听事件](#on)\n        - [scrollTo : 动画滚动](#scrollto)\n        - [moveTo : 瞬移](#moveto)\n        - [scrollToElement : 移动元素到wrap左上角](#scrolltoelement)\n        - [dampScroll : 衰减滚动](#dampscroll)\n        - [update : 更新\"可滑动范围\"](#update)\n        - [getContentRef : 获取content实例(其上有尺寸数据)](#getcontentref)\n        - [active : 激活content实例\"](#active)\n    - [事件](#事件)\n        - [scroll : 滚动](#事件)\n        - [scrollEnd : 滚动结束](#事件)\n        - [tap : 单击](#事件)\n        - [press : 按压](#事件)\n        - [pressup : 按压释放](#事件)\n        - [pan : 拖拽](#事件)\n        - [swipe : 滑动](#事件)\n        - [pinch : 缩放](#事件)\n        - [rotate : 旋转](#事件)\n- [进阶使用](#进阶使用)\n    - [支持更多手势(tap/press/pinch/rotate)](#支持更多手势)\n- [常见问题](#常见问题)\n    - [no-scroll : 不滚动](#no-scroll)\n    - [ResizeObserver : 监视内容变化](#监视内容变化)\n\n\n## 安装\n```shell\nnpm i any-scroll -S\n```\n[🚀返回目录](#目录)\n\n## 使用\n首先在页面构造如下html结构, 同时**给wrap一个固定尺寸**. \n```html\n\u003cdiv id=\"scroll-view\" style=\"height:600px;width:360px;\"\u003e\u003c!-- wrap --\u003e\n    \u003cdiv\u003e\u003c!-- content --\u003e\n        \u003c!-- 你的内容写在这里 --\u003e\n    \u003cdiv\u003e\n\u003c/div\u003e\n```\n\n初始化:\n```javascript\nimport AnyScroll from 'any-scroll';\nconst el = document.getElementById('scroll-view');\nconst as = new AnyScroll(el);\n\n// 滚动到x=-100,y=-100的位置.\nas.scrollTo([-100,-100]);\n\n// 只控制Y轴,1s内滑动到目标位置\nas.scrollTo({y:-100},1000);\n```\n[🚀返回目录](#目录)\n\n## API\n- [选项](#选项)\n- [实例属性](#实例属性)\n- [实例方法](#实例方法)\n- [事件](#事件)\n### 选项\n|名称|默认值|说明|\n|---|---|---|\n|**allow**|`[true,true]`|是否允许X或Y轴滚动,数组第一位控制X轴|\n|**damping**|`0.1`|[dampScroll](#dampScroll)的消损系数,范围0~1|\n|**overflowDistance**|`100`|允许超过边界的最大距离,单位\"px\"|\n|[render](#render)|[查看](#render)|控制content元素位置变化的函数|\n\n#### render\n默认通过**translate3d**控制content的位移, 如有需要也可改为控制**margin**或 **top(left)** 属性.\n```javascript\n// 默认\nfunction render(el, [x, y]) {\n    el.style.setProperty('transform',`translate3d(${x}px, ${y}px,0)`);\n}\n\n// 或者改为\nfunction render(el, [x, y]) {\n    el.style.setProperty('marginLeft', x+'px');\n    el.style.setProperty('marginTop', y+'px');\n}\n\nconst as = new AnyScroll({render});\n```\n[🚀返回目录](#目录)\n\n### 实例方法\n\n\n#### on\n监听事件, 默认继承了[any-touch](https://github.com/any86/any-touch)的所有手势事件.\n|事件名|说明|\n|---|---|\n|scroll|每次滚动|\n|scroll-end|滚动停止|\n|tap|单击|\n|press|按压|\n|pan|拖拽|\n|swipe|快滑|\n|rotate|旋转|\n|pinch|缩放|\n\n```javascript\nas.on('scroll-end',()=\u003e{\n    console.log('滚动停止了');\n})\n```\n[:rocket: 返回目录](#目录)\n\n#### scrollTo\n滚动到指定位置, 支持时间动画\n\n##### 参数\n|参数名|参考值|是否可选|说明|\n|---|---|---|---|\n|**distXY**|`[-100,-200]`或`{x:-100,y:-200}`|必选|目标位置|\n|**duration**|1000|可选|滚动时间,单位毫秒|\n|**easing**|[参考](https://github.com/component/ease/blob/master/index.js)|可选|缓动动画函数, 一般不需要修改|\n\n```javascript\n// 3秒钟移动到x=-100,y=-500的位置.\nas.scrollTo([-100,-500],3000);\n// 等价写法\nas.scrollTo({x:100,y:-500},3000);\n```\n\n[:rocket: 返回目录](#目录)\n\n#### moveTo\n瞬间移动到目标位置\n|参数名|参考值|是否可选|说明|\n|---|---|---|---|\n|**distXY**|`[-100,-200]`或`{x:-100,y:-200}`|必选|目标位置|\n```javascript\nas.moveTo([-100,-200]);\n```\n[:rocket: 返回目录](#目录)\n\n#### scrollToElement\n移动元素到wrap左上角.\n##### 参数\n|参数名|参考值|是否可选|说明|\n|---|---|---|---|\n|**el**|DOM元素|必选|目标元素|\n|**offset**|`[0,0]`或`{x:0,y:0}`|可选|对目标位置修正, 多滚动的距离|\n|**duration**|1000|可选|滚动时间,单位毫秒|\n|**easing**|[参考](https://github.com/component/ease/blob/master/index.js)|可选|缓动动画函数, 一般不需要修改|\n\n```javascript\n// 滚动到content中的子元素(child-1), 让其左上角和wrap的左上角重合.\nconst childEl = doucument.getElementById('child-1');\nas.scrollToElement(childEl);\n// 滚动到child-1下方100px的位置\nas.scrollToElement(childEl,{y:100});\n// 等价写法\nas.scrollToElement(childEl,[,100]);\n```\n\n[:rocket: 返回目录](#目录)\n\n\n#### dampScroll\n作用同scrollTo,只是滚动效果不同, 其不能指定时间. 仅供插件开发者使用, 模拟快速划动scrollView产生的滚动.\n\n##### 参数\n|参数名|参考值|是否可选|说明|\n|---|---|---|---|\n|**distXY**|`[-100,-200]`或`{x:-100,y:-200}`|必选|目标位置|\n|**damping**|默认0.1, 范围0~1|可选|不断靠近目标位置,每次靠近剩余距离的0.1倍.|\n```javascript\nas.dampScroll([-100,-200]);\n```\n[:rocket: 返回目录](#目录)\n\n#### update\n如果滚动范围出现异常, 可手动更新.\n```javascript\nas.update();\n```\n[:rocket: 返回目录](#目录)\n\n#### getContentRef\n获取content实例, 其上有尺寸等数据.\n##### 参数\n|参数名|参考值|是否可选|说明|\n|---|---|---|---|\n|**elOrIndex**|number或HTML元素|可选|[查看 ↓](#elOrIndex说明)|\n\n##### elOrIndex不同的值\n1. 如是number, 那么会按照wrap下的子元素索引取对应的content实例.\n2. 如是元素, 那么会递归向上找父元素, 直到找到对应的实例.\n3. 如果不传默认找当前[激活](#active)状态的content实例.\n\n```javascript\nas.getContentRef(1);\nas.getContentRef(childEl);\nas.getContentRef();\n\n```\n##### 返回值\ncontent实例或`null`.\n\n[:rocket: 返回目录](#目录)\n\n\n#### active\n如果有多个content实例, 激活指定content实例, 只有激活的content才会响应滚动. \n\n##### 参数\n|参数名|是否可选|\n|---|---|\n|**contentRef**|必选|\n```javascript\n// 激活第二个content实例.\nconst contentRef = as.getContentRef(1);\nas.active(contentRef);\n```\n[:rocket: 返回目录](#目录)\n\n\n\n### 实例属性\n\n#### el\nwrap元素\n```javascript\nas.el; // \u003cdiv class=\"any-scroll\"\u003e\u003c/div\u003e\n```\n[🚀返回目录](#目录)\n#### at\nany-scroll内部使用了any-touch手势库, 通过`as.at`可以访问any-touch的实例,从而修改手势行为等, [详情参考any-touch](https://github.com/any86/any-touch)\n```javascript\n// 仅对表单元素阻止触发\"默认事件\"\n// 这是any-touch参数的默认值, 在此仅做展示\nas.at.set({\n    preventDefault(e){\n        if (event.target \u0026\u0026 'tagName' in event.target) {\n            const { tagName } = event.target;\n            return !/^(?:INPUT|TEXTAREA|BUTTON|SELECT)$/.test(tagName);\n        }\n        return false;\n    }\n})\n```\n**注意:** 普通开发者谨慎使用, 修改不当会影响滚动效果, 如开发中遇到缺少功能, 大家尽量先[提Issue](https://github.com/any86/any-scroll/issues/new) \n\n[🚀返回目录](#目录)\n\n#### size\nwrap元素尺寸.\n```javascript\nconsole.log(as.size);\n```\n\n[🚀返回目录](#目录)\n\n### 事件\n\n```javascript\nas.on('scroll', context=\u003e{\n    // 当前位置信息\n    // context === as\n    console.log(context.xy);\n});\n```\n|事件名称|说明|\n|---|---|\n|**scroll**| 滚动|\n|**scrollEnd**| 滚动结束|\n|tap| 单击|\n|press| 按压|\n|pressup| 按压释放|\n|pan| 拖拽|\n|swipe| 滑动|\n|pinch| 缩放|\n|rotate| 旋转|\n\n\n除了\"**scroll**\"和\"**scroll-end**\", 其他事件都是any-touch实现的, 其事件对象上包含当前触点/距离/速度等信息, 更多请参考[any-touch](https://github.com/any86/any-touch)\n\n```javascript\nas.on('tap', e=\u003e{\n    // 当前触点x坐标\n    console.log(e.x)\n})\n```\n\n\n\n[🚀返回目录](#目录)\n\n## 进阶使用\n### 支持更多手势\nany-scroll基于any-touch开发, 所以也支持他的所有手势, 但是为了体积默认只加载了swipe/pan, 开启更多方法:\n```javascript\nimport AScroll from 'any-scroll';\nimport tap from '@any-touch/tap';\nimport swipe from '@any-touch/swipe';\nimport pinch from '@any-touch/pinch';\nimport rotate from '@any-touch/rotate';\n\nconst as = new AScroll();\n// 加载单击手势\nas.at.use(tap);\n// 加载快划\nas.at.use(swipe);\n// 加载缩放\nas.at.use(pinch);\n// 加载旋转\nas.at.use(rotate);\n\nas.on('tap',e=\u003e{\n\n});\n```\n\n[🚀返回目录](#目录)\n\n\n\n## 常见问题\n\n### no-scroll\n如果wrap下的子元素, 有些你并不想让他\"滚动\", 可以给其加\"no-scroll\"标记.\n```html\n\u003cdiv\u003e\n    \u003cdiv\u003e\u003c/div\u003e \u003c!-- 能滚动 --\u003e\n    \u003cdiv no-scroll\u003e\u003c/div\u003e \u003c!-- 不能滚动 --\u003e\n\u003c/div\u003e\n```\n\n[🚀返回目录](#目录)\n\n### 监视内容变化\n当content中的子元素发生变化(增/减去/尺寸), any-scroll需要重新计算\"**可滑动范围**\".\n\n默认any-scroll内部使用[ResizeObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver)([caniuse](https://caniuse.com/?search=ResizeObserver))监视wrap/content尺寸变化, 实现自动更新可滑动范围.\n\n![image](https://user-images.githubusercontent.com/8264787/147109689-ba1aeb91-da96-4a24-8ab1-29254c772f34.png)\n\n但其兼容性较差, 所以在不支持ResizeObserver的浏览器会使用[MutationObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver)([caniuse](https://caniuse.com/?search=MutationObserver))降级兼容, 其只能监视content的子元素的增/减, 从而更新滑动范围.\n![image](https://user-images.githubusercontent.com/8264787/147110880-a7c2f72f-82ba-4286-af8a-351332f00f4c.png)\n\n\n#### resize-observer-polyfill\n如果不在意体积, 可以使用\"**resize-observer-polyfill**\", 其可让ResizeObserver[兼容到最低IE9](https://github.com/juggle/resize-observer#tested-browsers).\n```javascript\nimport ResizeObserver from 'resize-observer-polyfill';\n// ⭐注入到全局\nwindow.ResizeObserver = ResizeObserver;\n\nimport AnyScroll from 'any-scroll';\nconst as = new AnyScroll(el);\n```\n\n##### 手动更新\n使用实例上的\"[update](#update)\"方法更新\"可滑动范围\". \n\n[🚀返回目录](#目录)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fany86%2Fany-scroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fany86%2Fany-scroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fany86%2Fany-scroll/lists"}