Smooth scroll when clicking a nav link - react js - react three fiber - html

so what I'm trying to achieve is a smooth scroll effect to a particular div on the page when I click a navbar div. I'm currently doing development with react-three-fiber and am using a custom scroll rig component . I am not too sure how to approach this. below can be found my code.
export default function App() {
const [loading, setLoading] = useState(false)
const [background, setBackground] = useState("base")
const phone = useRef()
useEffect(() => {
setTimeout(() => {
setLoading(true)
}, 2600)
}, [])
return (
<>
<Header />
{!loading ? <></> :
<Suspense>
<Canvas id={background} className="canvas-primary" camera={{ position: [0, 0, 5] }} gl={{ powerPreference: "high-performance", alpha: true, antialias: true, stencil: false, depth: true }} shadows >
<ambientLight intensity={0.5} />
<ScrollControls className='scroll-container' pages={15} >
<fog color="#161616" attach="fog" near={8} far={30} />
<BackgroundContext.Provider value={{ background, setBackground }}>
<Scene phone={phone} />
<MouseTracker phone={phone} />
<Physics allowSleep={false} iterations={15} gravity={[0, -200, 0]}>
{/* <Lamp position={[-3, 5, 0]} /> */}
</Physics>
</BackgroundContext.Provider>
<ContactShadows position={[0, -3.1, 0]} scale={10} blur={1.5} far={10} rotation={[Math.PI / 2, 0, 0]} />
<EffectComposer multisampling={15} disableNormalPass={true} >
<DepthOfField focusDistance={0} focalLength={0.02} bokehScae={2} height={480} />
<Bloom luminanceThreshold={0} luminanceSmoothing={10} height={300} opacity={1} />
</EffectComposer>
</ScrollControls>
<Html className="content"><Content /></Html>
</Canvas>
</Suspense>
}
</>
);
}
export default function Header() {
return (
<header className="primary-header">
<div className="middle">
<h1>SYMPHONY</h1>
</div>
<nav className='primary-navigation'>
<ul className="nav-area" >
<li className="item"><div id="About-us" className="link" onClick={() => handleClick(1)}>About Us</div></li>
<li className="item"><div id="D2C" className="link" onClick={() => handleClick(2)}>D2C Marketing</div></li>
<li className="item"><div id="B2B" className="link" onClick={() => handleClick("B2B")}>B2B Marketing</div></li>
<li className="item"><div id="Team" className="link" onClick={() => handleClick(4)}>Our Team</div></li>
</ul>
</nav>
<div id="et_mobile_nav_menu">
<div className="mobile_nav hidden">
<span className="select_page">Select Page</span>
<span className="mobile_menu_bar mobile_menu_bar_toggle"></span>
<ul id="mobile_menu" className="et_mobile_menu" style={{ display: "none" }}><li id="menu-item-377" className="menu-item menu-item-type-post_type menu-item-object-page menu-item-377 et_first_mobile_item">Marketing</li>
<li id="menu-item-376" className="menu-item menu-item-type-post_type menu-item-object-page menu-item-376">Web Design</li>
<li id="menu-item-374" className="menu-item menu-item-type-post_type menu-item-object-page menu-item-374">Resume</li>
<li id="menu-item-378" className="menu-item menu-item-type-post_type menu-item-object-page menu-item-378">Contact</li>
</ul>
</div>
</div>
</header >)
}
function handleClick(link) {
$("#B2B").on('click', function () { //id of the link which is being clicked
console.log(document.getElementsById('ID09'))
$('*').animate({
scrollTop: $("#ID09").offset().top //id of div to be scrolled
}, 1000);
});
}
export default function Content() {
return (
<div className="content">
<div id={"ID00"} >
<div className="Landing-page-content">
<div className="Landing-page-content-inner">
<h1>Your Marketing To The Next Generation</h1>
<h3> 5,000,000+ viewers</h3>
</div>
</div>
</div>
<div id={"ID01"} />
<div id={"ID02"} />
<div id={"ID03"} />
<div id={"ID04"} />
<div id={"ID05"} />
<div id={"ID06"} />
<div id={"ID07"} />
<div id={"ID08"} />
<div id={"ID09"} />
<div id={"ID010"} />
<div id={"ID011"} />
<div id={"ID012"} />
<div id={"ID013"} />
<div id={"ID014"} />
<div id={"ID015"} />
</div>
)
}
So, I have tried multiple approaches to this, the content component is a child to the main canvas which has an in build scrolling, However I am unsure how to manipulate the scroll bar of this particular component through vanilla js or jquery.

Related

How can I solve this using Knockout JS?

I have the following code, I am trying to get an id in the SPAN and it is not accepting values in any type of tag that is located inside ....
<div class="col-lg-12 col-md-12" id="contenedorListaTarea">
<ul class="nav nav-tabs align-items-lg-start mb-1" data-bind="foreach: loterias">
<li class="nav-item" name="loteria" data-bind="click:namerjarClickLoteria">
<a class="nav-link fontSizeTab" data-bind="text: nombre,style: { backgroundColor: color},attr:{id:id+nombreCorto}">
<span data-bind="attr:{id:nombreCorto}" >0.00</span>
</a>
</li>
</ul>
</div>
If I understand you correctly your problem is that any tag placed in <a> tag is to being rendered. The reason for that to happen is that your <a> tag is using text: nombre binding which is replacing anything you have put inside it.
I removed that binding and <span> started to appear in it with working attr binding.
var viewModel = function() {
this.loterias = ko.observableArray([
{
nombre: 'test',
color: 'red',
id: 'test-id',
nombreCorto: 1,
namerjarClickLoteria: function(){
}
},
{
nombre: 'test',
color: 'green',
id: 'test-id',
nombreCorto: 2,
namerjarClickLoteria: function(){
}
}
]);
return this;
}
ko.applyBindings(viewModel(), $('#contenedorListaTarea')[0]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="col-lg-12 col-md-12" id="contenedorListaTarea">
<ul class="nav nav-tabs align-items-lg-start mb-1" data-bind="foreach: loterias">
<li class="nav-item" name="loteria" data-bind="click:namerjarClickLoteria">
<a class="nav-link fontSizeTab" data-bind="style: { backgroundColor: color},attr:{id:id+nombreCorto}">
<span data-bind="attr:{id:nombreCorto}" >0.00</span>
</a>
</li>
</ul>
</div>

ReactJS: Navbar Current Page Effect

I want the highlight effect when I'm on the current page. For example, if I'm on the About Page, I woudl like About to be highlighted in the navbar.
How would I do that?
Relevant Code
NavBar.js
function NavBar() {
const [open, setOpen] = useState(false);
NavBar.handleClickOutside = () => setOpen(false);
return(
<nav>
<div className='navbar-container'>
<a href='/' className='logo'>Daniel Zhang</a>
<div className='toggle-button' onClick={() => setOpen(!open)}>
<div className='bar' />
<div className='bar' />
<div className='bar' />
</div>
</div>
<div id='nav-links' className={open ? 'nav-open' : 'nav-collasped'}>
<a href='/'>Home</a>
<a href='/about'>About</a>
{/* <a href='/blog'>Blog</a> */}
<a href='/contact'>Contact</a>
</div>
</nav>
);
}
const clickOutsideConfig = {
handleClickOutside: () => NavBar.handleClickOutside,
};
export default onClickOutside(NavBar, clickOutsideConfig);
You could use the NavLink component from react router dom. Import like:
import { NavLink } from 'react-router-dom';
And instead of <a href='/about'>About</a> you can write:
<NavLink exact to='/about' activeClassName="highlighted">About</Navlink>
And so on for the other links present within the <div id='nav-links'.
Of course you can add the highlighted styles based on the .highlighted
More info, see https://reactrouter.com/web/api/NavLink

VUE: How to multiple component partials in one file?

home.vue
<template>
<app-navbar>
<logo title="navbar"></logo>
<div class="navbar-collapse">
<link href="#first" title="first link"></link>
<link href="#second" title="second link"></link>
<link href="#third" title="third link"></link>
</div>
</app-navbar>
</template>
<script>
export default {
name: "Home",
components: {
AppNavbar: () => import('#/components/navbar.vue')
}
}
</script>
navbar.vue
<script>
export default {
name: "AppNavbar",
props: {
title: {
type: String,
default: "navbarDemo"
},
href: {
type: String,
default: "#"
}
},
template: `
<div class="navbar-container">
<component :is="logo">
<div class="navbar-brand">{{ title }}</div>
</component>
<ul>
<component :is="link">
<li class="item">
<a :href="href" class="link">{{ title }}</a>
</li>
</component
</ul>
</div>
</div>
`
};
</script>
I WANT THIS
<div class="navbar-container">
<div class="navbar-brand">navbar</div>
<div class="navbar-collapse">
<ul>
<li class="item">
first link
</li>
<li class="item">
second link
</li>
<li class="item">
third link
</li>
</ul>
</div>
</div>
What am I doing wrong? Is component used differently? I want to use a component and have another component in it in one file (I don't want to have 20 files here just for navbar). Then compose the structure in this way. Possible?
I'm trying a similar HTML structure as here: link
Here is what you need:
home.vue
<app-navbar :links="links">
<template #logo>
<img src=""/>
</template>
</app-navbar>
data() {
return {
links: [
{ href: '#first", title: 'first link' },
{ href: '#second", title: 'secondlink' },
{ href: '#third", title: 'thirdlink' },
]
}
}
navbar.vue
<template>
<div class="navbar-container">
<div class="navbar-brand">
<slot name="logo" />
</div>
<div class="navbar-collapse">
<ul>
<li v-for="link in links" :key="link.href">
<a :href="link.href">{{ link.title }}</a>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
links: Array
}
}
</script>
The logo element is passed through a slot (https://fr.vuejs.org/v2/guide/components-slots.html).
You understood <component> wrongly :p <component> do not declare a component, it's only a way to use a component when its name might change.
Instead of writing
<comp1 v-if="test" /> <comp2 v-else /> you could write <component :is="test ? 'comp1" : 'comp2' />. But comp1 and comp2 components still need to be declared somewhere and imported.
Did you check https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components ?
EDIT: If you want to customize links with scoped-slots:
home.vue
<app-navbar :links="links">
<template #logo>
<img src=""/>
</template>
<template #link="{ href, title }">
<a :href="href">{{ title }}</a>
</template>
</app-navbar>
data() {
return {
links: [
{ href: '#first", title: 'first link' },
{ href: '#second", title: 'secondlink' },
{ href: '#third", title: 'thirdlink' },
]
}
}
navbar.vue
<template>
<div class="navbar-container">
<div class="navbar-brand">
<slot name="logo" />
</div>
<div class="navbar-collapse">
<ul>
<li v-for="link in links" :key="link.href">
<slot name="link" :href="link.href" :title="link.title" />
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
links: Array
}
}
</script>
So the looped links are passed through the slot so the parent is handling the rendering

Href link issues

I am trying to display all the projects I have coded in my career for my portfolio. I made them into an obj called projects and have mapped through them to render. The problem is that a lot of them are not deployed yet so, for those I want an alert saying "not linked yet" but the link is defaulted to local:3000 and just reloads the page
portfolio: [
{
name: "OmniFood",
description: "",
imgurl: "https://media.giphy.com/media/hvLOGi1KsF02XiZ1DD/giphy.gif",
href: "https://github.io/SbOmniFood/"
},
{
name: "Forkify",
description: "",
imgurl: "https://media.giphy.com/media/ekeOYzzNEpW73RIcSb/giphy.gif",
href: ""
},
{
name: "Connect Four",
description: "",
imgurl: "https://media.giphy.com/media/YrC2lEAcG4loOj2aLI/giphy.gif",
href: ""
},
here is how i render it.
<section id="portfolio">
<h1>Check Out Some of My Projects!</h1>
<div className="portfolioGrid">
{resumeData.portfolio &&
resumeData.portfolio.map(item => {
return (
<a href={`${item.href}`} target="_blank">
<div className="portfolio-item portfolioGridSquare">
<div className="item-wrap">
<div>
<img
src={`${item.imgurl}`}
alt="my projects"
className="item-img"
/>
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{item.name}</h5>
<p>{item.description}</p>
</div>
</div>
</div>
</div>
</div>
</a>
);
})}
<div id="portfolio-wrapper" className=""></div>
</div>
</section>
You should only render a link if the project has a valid href. For example:
const PortfolioList = () => (
<div className="portfolioGrid">
{portfolio.map(item => item.href ? (
<a href={item.href} target="_blank">
<PortfolioItem item={item} />
</a>
) : (
<div onClick={() => alert("not linked yet")}>
<PortfolioItem item={item} />
</div>
))}
</div>
);
const PortfolioItem = ({ item }) => (
<div className="portfolio-item portfolioGridSquare">
<div className="item-wrap">
<div>
<img src={`${item.imgurl}`} alt="my projects" className="item-img" />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{item.name}</h5>
<p>{item.description}</p>
</div>
</div>
</div>
</div>
</div>
);

how to apply bootstrap active class to an onclick

How do you apply a bootstrap class like nav-link active to a onlick(). I've been having hard time implementing this. I thought it would have just been as simple as.
<a
onClick={() => this.props.onUpdateSelectedProbe(probe)}
className="dropdown-item nav-link active"
>
But this however just makes all list items/anchor tags active.
return (
<div style={{ alignSelf: "center" }}>
<ul className="nav nav-pills">
<li className="nav-item dropdown ">
<div
className="dropdown-menu show"
x-placement="bottom-start"
style={{
position: "relative",
willChange: "transform",
top: "5px",
overflowY: "scroll",
maxHeight: "200px"
}}
>
{this.props.searchState.isActive === false
? probes.map(probe => (
<a
onClick={() => this.props.onUpdateSelectedProbe(probe)}
className="dropdown-item"
>
<div
className="dropdown-divider"
style={{ backgroundColor: "black" }}
></div>
{probe.companyPN}: {probe.description}
</a>
))
: filteredProbes.map(filterprobe => (
<a
onClick={() =>
this.props.onUpdateSelectedProbe(filterprobe)
}
className="dropdown-item"
>
<div className="dropdown-divider"></div>
{filterprobe.companyPN}: {filterprobe.description}
</a>
))}
</div>
</li>
</ul>
</div>
);
This is a basic example of adding items to a list and conditionally showing a "selected" class
.selected {
background: red;
}
function App() {
const [people] = useState([
{ id: 0, name: "Mario" },
{ id: 1, name: "Luigi" },
{ id: 2, name: "Peach" }
]);
const [selected, setSelected] = useState({});
return (
<div>
{people.map(({ id, name }) => (
<div
className={selected[id] ? "selected" : ""}
key={id}
onClick={() => setSelected({ ...selected, [id]: true })}
>
{name}
</div>
))}
</div>
);
}
https://codesandbox.io/s/funny-nobel-e6x6e