how i can THREEJs TextGeomtry added more verties? - three.js

i use dependencies
"#react-three/drei": "7.5.1",
"#react-three/fiber": "6.2.3",
"#types/three": "0.128.0",
/* eslint-disable new-cap */
/* eslint-disable no-nested-ternary */
import React, { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
import * as THREE from 'three';
import { useThree } from '#react-three/fiber';
import BMJUA from './BMJUA.json';
import GeometryUtils from './GeometryUtils';
const Particle = ({
children,
vAlign = 'center',
hAlign = 'center',
size = 40,
color = '#0000ef',
ref,
}: any) => {
const font = new THREE.FontLoader().parse(BMJUA);
const config = useMemo(
() => ({ font, size: 40, height: 3, bevelSegments: 5, step: 10 }),
[font]
);
const textGeoRef = useRef<THREE.TextGeometry>();
return (
<group ref={ref}>
<points>
<textGeometry
ref={textGeoRef}
attach="geometry"
args={[children, config]}
/>
<pointsMaterial size={1} sizeAttenuation vertexColors color="lime" />
</points>
</group>
);
};
export default Particle;
i tried text with points mesh
But I got the missing points.
my program screen
Why are there no intermediate midpoints?
I want to add a function to adjust the position of the text point.
Please help me

Related

Three JS GLTF Loader Not Working with Nuxt 3

I'm facing an error when implementing three JS Gltf Loader with nuxt 3.
Error message :
" Uncaught (in promise) TypeError: Class constructor Loader cannot be invoked without 'new' .. "
versions:
"three": "^0.148.0",
"three-gltf-loader": "^1.111.0"
<template>
<div ref="container"></div>
</template>
<script>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import GLTFLoader from "three-gltf-loader";
export default {
setup() {
const container = ref(null);
const scene = ref(new THREE.Scene());
const renderer = ref(new THREE.WebGLRenderer({ antialias: true }));
const width = 700;
const height = 700;
const camera = ref(
new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)
);
const loader = ref(new GLTFLoader());
onMounted(async () => {
renderer.value.setSize(
container.value.clientWidth,
container.value.clientHeight
);
container.value.appendChild(renderer.value.domElement);
camera.value.position.z = 5;
const response = await fetch("logo.gltf");
const gltf = await response.json();
loader.value.parse(
gltf,
"",
(gltf) => {
scene.value.add(gltf.scene);
renderer.value.render(scene.value, camera.value);
},
undefined,
(error) => {
console.error(error);
}
);
});
return { container };
},
};
</script>
"three": "^0.148.0", "three-gltf-loader": "^1.111.0"
This kind of setup isn't recommended since you can import the latest GLTFLoader module from the three repository. Try it again with these imports:
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
I found a solution on Alvaro Dev Labs' YT channel, he used TroisJS instead of ThreeJS ( in fact, it's Vite + Three).
And for nuxt 3 you just need to add ".client.vue " to the file name of your component to run it on the client side (Model.client.vue).
<script lang="ts">
import { defineComponent, ref, onMounted } from "vue";
import {
Renderer,
Scene,
Camera,
PointLight,
AmbientLight,
GltfModel,
} from "troisjs";
export default defineComponent({
components: {
Renderer,
Scene,
Camera,
PointLight,
AmbientLight,
GltfModel,
},
setup() {
const renderer = ref(null);
const model = ref(null);
function onReady(model) {
console.log("Ready", model);
}
onMounted(() => {
renderer?.value?.onBeforeRender(() => {
model.value.rotation.x += 0.01;
});
});
return {
renderer,
model,
onReady,
};
},
});
</script>
<template>
<div>
<Renderer ref="renderer" antialias orbit-ctrl resize="window">
<Camera :position="{ x: -10, z: 20 }" />
<Scene background="#fff">
<AmbientLight />
<PointLight
color="white"
:position="{ x: 100, y: 1000, z: 40 }"
:intensity="1"
/>
<GltfModel ref="model" src="/Models/logo.gltf" #load="onReady" />
</Scene>
</Renderer>
</div>
</template>
import like this
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
Then use like this
const loader = new GLTFLoader()

Yjs y-webrtc simple peer issue (Yjs + codemirror 6, sync content among editors)

I am using Yjs with codemirrow 6 in my project. I followed codemirror 6 examples and Yjs codemirror.next example (https://github.com/yjs/y-codemirror.next) in github.
And when I ran it, I got this error.
Here is the source.
Please help.
Any idea is appreciated. Thanks.
================
Update 1
Here is my demo.ts
import * as Y from 'yjs'
// #ts-ignore
import { yCollab, yUndoManagerKeymap } from 'y-codemirror.next'
import { WebrtcProvider } from 'y-webrtc'
import {EditorState, EditorView, basicSetup} from "#codemirror/next/basic-setup"
import {html} from "#codemirror/next/lang-html"
//import {esLint} from "#codemirror/next/lang-javascript"
// #ts-ignore
//import Linter from "eslint4b-prebuilt"
//import {linter} from "#codemirror/next/lint"
//import {StreamLanguage} from "#codemirror/next/stream-parser"
//import {javascript} from "#codemirror/next/legacy-modes/mode/javascript"
import * as random from 'lib0/random'
export const usercolors = [
{ color: '#30bced', light: '#30bced33' },
{ color: '#6eeb83', light: '#6eeb8333' },
{ color: '#ffbc42', light: '#ffbc4233' },
{ color: '#ecd444', light: '#ecd44433' },
{ color: '#ee6352', light: '#ee635233' },
{ color: '#9ac2c9', light: '#9ac2c933' },
{ color: '#8acb88', light: '#8acb8833' },
{ color: '#1be7ff', light: '#1be7ff33' }
]
// select a random color for this user
export const userColor = usercolors[random.uint32() % usercolors.length]
const ydoc = new Y.Doc()
const provider = new WebrtcProvider('codemirror.doc', ydoc)
const ytext = ydoc.getText('codemirror')
const undoManager = new Y.UndoManager(ytext)
provider.awareness.setLocalStateField('user', {
name: 'Anonymous ' + Math.floor(Math.random() * 100),
color: userColor.color,
colorLight: userColor.light
})
let state = EditorState.create({doc: ytext.toString(), extensions: [
basicSetup,
html(),
yCollab(ytext, provider.awareness, { undoManager })
// linter(esLint(new Linter)),
// StreamLanguage.define(javascript),
]})
;(window as any).view = new EditorView({state, parent: document.querySelector("#editor")!})

new Image() in Next.js?

Can you use new Image() inside the Next.js? I am getting error, saying it is not defined.
I know I can simply use inside JSX, but in this case, I am not sure if it will work, as I must reference the image outisde JSX, as shown below.
If there is no way to make new Image() work with Next.js, please show a different way to make this work. This new Image() is for making a GSAP scroll animation work.
Here is my code:
import Link from 'next/link'
import Head from 'next/head'
import Image from 'next/image'
import {useEffect, useRef, useState} from 'react'
import styles from '../styles/Home.module.css'
import {gsap} from 'gsap'
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
const Home = () => {
const viewer = useRef(null)
const image = new Image();
if (typeof window !== "undefined") {
gsap.registerPlugin(ScrollTrigger);
}
useEffect(()=>{
const rows = 5
const columns = 10
const frame_count = rows * columns - 1
// const imageWidth = 6336
// const imageHeight = 1782
const imageWidth = 4049
const imageHeight = 3000
const horizDiff = imageWidth / columns
const vertDiff = imageHeight / rows
const ctx = viewer.current.getContext("2d");
viewer.current.width = horizDiff;
viewer.current.height = vertDiff;
const image = new Image()
image.src = "./spriteDesk.jpg";
// image.src = "./spriteMobile.jpg";
image.onload = () => onUpdate();
const setPos = gsap.quickSetter(viewer.current, "background-position");
const obj = {num: 0};
gsap.to(obj, {
num: frame_count,
ease: "steps(" + frame_count + ")",
scrollTrigger: {
trigger: ".section-one",
start: "top top",
end: "+=" + imageHeight,
pin: true,
anticipatePin: 1,
scrub: 1
},
onUpdate
});
function onUpdate() {
ctx.clearRect(0, 0, horizDiff, vertDiff);
const x = Math.round((obj.num % columns) * horizDiff);
const y = Math.round(Math.floor(obj.num / columns) * vertDiff);
ctx.drawImage(image, x, y, horizDiff, vertDiff, 0, 0, horizDiff, vertDiff);
}
},[])
return (
<>
<Head>
<title>TalkingSkunk | Home</title>
<meta name='keywords' content='talkingskunk' />
<link rel="icon" href="/favicon.ico" />
{/* <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/ScrollTrigger.min.js"></script> */}
</Head>
{/* <div className={styles.bgWrap}>
<Image
src="/spriteDesk.png"
className='cityscape'
data-speed="0.2"
layout="fill"
objectFit="cover"
quality={100}
/> */}
{/* <Image src ='/spriteDesk.jpg' alt="spriteDesk" width ={4049} height = {3000} /> */}
{/* <p className={styles.bgText}>
Discover
</p> */}
<section className="styles.scene styles.section section-one">
<canvas ref={viewer} className="styles.viewer"></canvas>
</section>
</>
)
}
export default Home;
If anyone still needs this it can be accomplished by following the next steps:
Replace import Image from 'next/image' with import NextImage from 'next/image' (or anything similar),
Replace all <Image ... tags with <NextImage ... (or, if you don't have any, than just remove the import)
Use The Image() constructor to create a new HTMLImageElement instance described on mdn page.
In case you use Next.js version 11+ (or earlier) use one of the solutions described on this question to disable no-img-element lint in order to prevent the error.

react-native reanimated does not respond to onFocus and onBlur

What I am trying to do
I need to animate a View's background color when a text input is focused.
What I did until now
I built a component that has two functions, onFocus and onBlur - it's just an event function from react-native-reanimated.
const onFocus = event<NativeSyntheticEvent<TextInputFocusEventData>>([
{
nativeEvent: ({ target }) => set(colorAnimation, 1)
}
]);
const onBlur = event<NativeSyntheticEvent<TextInputFocusEventData>>([
{
nativeEvent: ({ target }) => set(colorAnimation, 0)
}
]);
I am passing this function to an Animated TextInput, I get no error on console and it shows the custom background color that I've set. But not changing on Focus or Blur.
Code
I am using typescript
import React from 'react';
import { NativeSyntheticEvent, TextInputFocusEventData } from 'react-native';
import Reanimated from 'react-native-reanimated';
import { bInterpolateColor } from 'react-native-redash';
import styled from 'styled-components/native';
const { Clock, Value, event, set, debug, block, divide } = Reanimated;
const StyledTextInput = styled.TextInput`
height: 40px;
padding: ${props => props.theme.spacing.default * 2}px
${props => props.theme.spacing.default * 3}px;
`;
const AnimatedTextInput: typeof StyledTextInput = Reanimated.createAnimatedComponent(
StyledTextInput
);
const Container = styled(Reanimated.View)`
width: 100%;
border: 1px solid ${props => props.theme.colors.border};
background: #e3e7eb;
border-radius: ${props => props.theme.shapping.borderRadius * 2};
`;
const TextInput = () => {
const clock = new Clock();
const colorAnimation = new Value(0);
const onFocus = event<NativeSyntheticEvent<TextInputFocusEventData>>([
{
nativeEvent: ({ target }) => set(colorAnimation, 1)
}
]);
const onBlur = event<NativeSyntheticEvent<TextInputFocusEventData>>([
{
nativeEvent: ({ target }) => set(colorAnimation, 0)
}
]);
return (
<Container
style={{
backgroundColor: bInterpolateColor(
colorAnimation,
{ r: 255, g: 0, b: 0 },
{ r: 0, g: 0, b: 255 }
)
}}
>
<AnimatedTextInput onFocus={onFocus} onBlur={onBlur} />
</Container>
);
};
export default TextInput;
Result
from what I can see you're not using binterpolatecolor correctly.
from the doc:
const bInterpolateColor: (value: Animated.Adaptable<number>, color1: string | number, color2: string | number, colorSpace?: "hsv" | "rgb") => Animated.Node<number>;
you are not providing the colorspace (but this is optional so I don't know how relevant that is), also color 1 and color 2 can only be string or number and you've given an object it seems.
so that's the first problem, I am also not sure if your container component will update without some sort of state change via setstate(), but I could be wrong as I'm not a reanimated expert by any means.

Full-width image with aspect ratio in React Native

I want to require() a static image in a Home screen component I've written, and I want that image to be the full width of the display (which here happens to also be the full width of the container) while maintaining the aspect ratio.
Here is what I have so far. The Home component:
import React, { Component } from "react";
import {
StatusBar,
} from "react-native";
import Container from "../components/Container/Container";
import Header from "../components/Header/Header";
import FullWidthImage from "../components/Images/FullWidthImage";
export default class Home extends Component {
render() {
return (
<Container>
<FullWidthImage source={require("./lifting.jpg")}/>
<Header/>
<StatusBar translucent={false}/>
</Container>
);
}
}
And the FullWidthImage component:
import React, { Component } from "react";
import { View, Image, StyleSheet } from "react-native";
import Proptypes from "prop-types";
export default class FullWidthImage extends Component {
render() {
return (
<Image source={this.props.source} style={style.image} resizeMode="contain"/>
);
}
}
const style = StyleSheet.create({
image: {
flex: 1,
width: "100%",
borderColor: "red", borderWidth: 2,
}
});
I've been trying for a while and looking around on SO for a good answer but I can't find one (for an example some of them assume you have an uri and are not using require()). Greatly appreciate the help!
Here is what I ended up doing:
I created the following component
import React, { Component } from "react";
import { View, Image, StyleSheet, Dimensions } from "react-native";
import Proptypes from "prop-types";
export default class FullWidthImage extends Component {
static propTypes = {
requireSource: Proptypes.number // is actually a require(some-url)
};
render() {
let image = this.props.requireSource;
const { width, height } = Image.resolveAssetSource(image);
const ratio = height / width;
const SCREEN_WIDTH = Dimensions.get('window').width;
return (
<Image source={image} style={{width: SCREEN_WIDTH, height: SCREEN_WIDTH*ratio}} resizeMode="contain"/>
);
}
}
And then I use it in my Home component like this:
This way I can have the image I want to show in a component in the same folder as that component.
Note: The formatting of this answer seems messed up, don't know how to fix it, I tried ctrl+k on the code snippets.
You can use the not so well documented library resolveAssetSource.
Like this:
import {
Platform,
StyleSheet,
Text,
Image,
View,
Dimensions,
} from 'react-native';
var resolveAssetSource = require('resolveAssetSource');
var imgSrc = resolveAssetSource(require('./200x150.png'));
console.log(imgSrc.width, imgSrc.height);
const SCREEN_WIDTH = Dimensions.get('window').width;
const IMAGE_RATIO = imgSrc.height/imgSrc.width;
...
<Image source={imgSrc}
style={{width:SCREEN_WIDTH, height:SCREEN_WIDTH*IMAGE_RATIO}}/>
...
The important being: var imgSrc = resolveAssetSource(require('./200x150.png'));
I used this issue to get the answer, and then I went and try it ; )
https://github.com/facebook/react-native/issues/4025
Use resizeMode (https://facebook.github.io/react-native/docs/image.html#style)
resizeMode: "cover"
In your code:
...
const style = StyleSheet.create({
image: {
flex: 1,
width: "100%",
borderColor: "red", borderWidth: 2,
resizeMode: "cover"
},
container: {flex:1}
});
Or try with other types: contain, cover, stretch, center, repeat.

Resources